Workspace contract

The runtime loads configuration recursively from config/. Filenames are organizational only; semantics come from the YAML object kind, metadata, and spec. This keeps the repository flexible while preserving a stable contract for discovery.

config/
  workspace.yaml
  agent-context.md
  catalogs/
    models.yaml
    embedding-models.yaml
    stores.yaml
    vector-stores.yaml
    tools.yaml
    backends.yaml
    mcp.yaml
  agents/
    direct.yaml
    orchestra.yaml

YAML principles

  • Use YAML for assembly, policy, and reusable catalog state.
  • Do not invent harness-specific semantics where upstream already defines the primitive.
  • Keep collection files Kubernetes-style with apiVersion, plural kind, and spec: [].
  • Keep singleton runtime config as one document with metadata and spec.

Avoid semantic duplication

YAML should expose upstream concepts directly where possible. The goal is not to create a second agent framework inside configuration.

workspace.yaml: runtime-level settings only

Treat workspace.yaml as the runtime singleton. It should express application-level routing, recovery, concurrency, maintenance, and runtime defaults. It should not become a dump of agent-private behavior or prompt-level details.

Tool-module discovery policy also belongs here. Use it when the runtime should keep YAML catalogs recursive but limit local resources/tools/-style module loading to files directly under each tool root.

apiVersion: agent-harness/v1alpha1
kind: Workspace
metadata:
  name: default
spec:
  runtime:
    runtimeRoot: ./.agent
    defaults:
      governance:
        toolPolicy: default
    recovery:
      resumeResumingRequestsOnStartup: true
    maintenance:
      enabled: true
    concurrency:
      maxConcurrentRuns: 4
    toolModuleDiscovery:
      scope: top-level
  routing:
    defaultAgent: orchestra
Put here

Routing defaults, concurrency policy, maintenance, recovery, tool-module discovery policy, and runtime-owned governance defaults.

Do not put here

Agent prompt fragments, backend-private tuning knobs, or transient request state.

Catalog files and what each one owns

Catalogs should answer one question clearly: what reusable named object is this file responsible for? Keep each catalog narrow so users know where to add the next thing without scanning the whole repository.

models.yaml

Named chat model presets. Start with one default model and one obvious fallback.

apiVersion: agent-harness/v1alpha1
kind: Models
spec:
  - metadata:
      name: model/default
    provider: openai
    model: gpt-5.4
    temperature: 0.2

  - metadata:
      name: model/fallback
    provider: anthropic
    model: claude-sonnet-4-5

embedding-models.yaml

Named embedding presets used by vector stores and semantic recall.

apiVersion: agent-harness/v1alpha1
kind: EmbeddingModels
spec:
  - metadata:
      name: embedding/default
    provider: openai
    model: text-embedding-3-large

stores.yaml

Durable structured persistence and checkpoint recovery. Keep stores and checkpointers distinct.

apiVersion: agent-harness/v1alpha1
kind: Stores
spec:
  - metadata:
      name: store/default
    kind: Store
    storeKind: SqliteStore
    url: ./.agent/runtime.db

  - metadata:
      name: checkpointer/default
    kind: Checkpointer
    storeKind: SqliteCheckpointer
    url: ./.agent/runtime.db

vector-stores.yaml

Semantic recall and embedding-backed lookup. This is not the same thing as the canonical durable store.

apiVersion: agent-harness/v1alpha1
kind: VectorStores
spec:
  - metadata:
      name: vector/default
    storeKind: LibSQLVectorStore
    url: ./.agent/runtime.db
    table: memory_embeddings
    embeddingModelRef: embedding/default

backends.yaml

Named backend presets. Keep these simple and focused on backend selection.

apiVersion: agent-harness/v1alpha1
kind: Backends
spec:
  - metadata:
      name: backend/deepagent-default
    backend: deepagent

  - metadata:
      name: backend/langchain-default
    backend: langchain-v1

tools.yaml

Named tool resources or references. The implementation still lives under resources/tools/.

apiVersion: agent-harness/v1alpha1
kind: Tools
spec:
  - metadata:
      name: tool/write-file
    source: local
    toolName: write_file

mcp.yaml

Named MCP servers. Use catalogs for remote, shared capability surfaces rather than burying them in agents.

apiVersion: agent-harness/v1alpha1
kind: McpServers
spec:
  - kind: McpServer
    id: awesome-github-mcp
    name: awesome-mcp/github-mcp
    description: MCP server for GitHub workflows and repository operations
    repositoryUrl: https://github.com/modelcontextprotocol/servers
    transport: stdio
    command: npx
    args:
      - -y
      - "@modelcontextprotocol/server-github"
    env:
      GITHUB_TOKEN: CHANGE_ME

Treat id as the runtime identity. Fields such as transport, command, args, url, env, cwd, token, and headers drive runtime behavior; richer fields such as name, description, and repositoryUrl are useful catalog metadata.

Keep the server preset in the catalog, then attach it from agents with an object-form spec.mcpServers usage entry. That is where per-agent tool filters and transport overrides belong.

Agent definitions

Agent is the primary product configuration object. Subagents are simply agents referenced by another agent through spec.subagents. Routing answers which host agent starts a run; it should not introduce a second harness-owned role taxonomy.

apiVersion: agent-harness/v1alpha1
kind: Agent
metadata:
  name: orchestra
spec:
  backend: deepagent
  modelRef: model/default
  runtime:
    runtimeRoot: ./.agent
  tools: []
  skills: []
  subagents: []
  mcpServers: []

In practice, most teams should write at least two agent examples: one direct-response agent and one orchestrating agent that can call subagents.

apiVersion: agent-harness/v1alpha1
kind: Agent
metadata:
  name: direct
spec:
  backend: langchain-v1
  modelRef: model/default
  runtime:
    runtimeRoot: ./.agent
  tools:
    - tool/write-file
  skills: []
  mcpServers: []
  subagents: []

---
apiVersion: agent-harness/v1alpha1
kind: Agent
metadata:
  name: orchestra
spec:
  backend: deepagent
  modelRef: model/default
  runtime:
    runtimeRoot: ./.agent
  tools:
    - tool/write-file
  skills:
    - repo-review
  mcpServers:
    - ref: mcp/awesome-github-mcp
      toolFilters:
        - "^issue_"
  subagents:
    - direct

Catalogs and reusable objects

Catalog documents let teams name and reuse models, embedding models, stores, vector stores, tools, MCP servers, and backends. The runtime compiles those named objects into the final agent bindings.

Models

Named chat model presets with provider, model id, and provider options.

Stores and checkpointers

Durable runtime persistence and recovery configuration.

Tools

Reusable tool definitions or catalog references for agents to whitelist.

MCP servers

Shared remote capability endpoints, usually heavier than local tools.

Assembly flow

  1. Load YAML documents from the workspace.
  2. Discover local resources such as resources/tools/ and resources/skills/.
  3. Resolve named references from catalogs into compiled agent bindings.
  4. Attach runtime-owned policy, persistence, recovery, and governance defaults.
  5. Expose one stable runtime surface to the application.

Common mistakes

Confusing store vs checkpointer vs vector store

Structured persistence, recovery, and semantic recall are related, but they are not one object.

Putting implementation in catalogs

Catalogs name resources. Tool code still belongs in resources/tools/ and app code in src/.

Overloading workspace.yaml

Keep runtime policy there. Do not turn it into a second agent prompt or a backend tuning dump.

Inventing harness-only semantics

If upstream already has the primitive, map it cleanly instead of renaming it in YAML.

What not to do in YAML

Do not use YAML to encode transient request state, checkpoint internals, or app-private view models. YAML is for assembly and operating policy, not for ad hoc duplication of runtime data.