Skip to content

Manifest pipeline

How build_agent(manifest, deps) turns a parsed manifest into a runnable Agent. Source: packages/harness/src/felix/manifests/builder.py in felix-run/felix.

Manifests use apiVersion: felix/v1, kind: Agent (Pydantic v2, extra=forbid). Request handlers resolve the document first (tenant Postgres active version → bundled YAML under manifests/), then pass the Manifest object into the builder.

BuildDeps carries the ToolProvider, optional auth, session store/strategy, object store, settings, and sub-agent builder (tests stub children here).

  1. Validate — re-check schema + cross-field rules (single vs multi-agent, pattern registry kind, durable + checkpointer constraints).

  2. System prompt — join soul (if enabled) + system_prompt.base + inline.

  3. Skills — build the catalog (host directories, then the tenant library’s live versions, then operator uploads for declared refs) and append it to the prompt as an <available_skills> block of names and descriptions; bind list_skills / activate_skill / deactivate_skill / read_skill_file, which return a body only on activation. With spec.skill_authoring.enabled, also bind create_skill, update_skill and submit_skill_feedback — before governance, so an approvals rule holds them.

  4. External tools — bind MCP servers (server__tool), A2A peers (peer__name), sandboxes, containers, queues (Valkey/Redis lists), browser tools (Playwright extra). Bind failures are logged; the rest of the agent still builds.

  5. Sub-agents / local tools — multi-agent patterns build children; single-agent resolves spec.tools from the provider. Auto-inject memory / procedural / read_artifact when enabled — all before governance, so they are gated like any other tool. pattern: deep injects plan tools before governance so they are gated like everything else.

  6. Governance pipeline (innermost → outermost on the call path):

    secret masking → policies → command screening → content screening
    → limits → guardrails → LLM judges → approvals → (artifact spill)

    See governance.

  7. Pattern dispatch — get_pattern(spec.pattern) from the open registry (react, deep, router, parallel, groupchat, reflect, plan_execute, plus any registered plugins).

  8. Durable wrap — when spec.execution.mode: durable, wrap so invoke enqueues a fiber and returns a resume token.

Concern Resolution
Checkpointer memory.checkpointer → resolved through the checkpointer registry: postgres (default), none, or a plugin-registered store
Strategy session.strategy → full_replay / windowed:N / summarizing:N / semantic:N / compacting
Long-term memory memory.recall.tools binds remember / recall / forget / list_memories (not under store: none); memory.store ∈ {pgvector, memory} builds the active-facts prelude
Artifacts Large tool outputs spill to the object store; read_artifact is bound so the model can page through them, limited to its own conversation’s

Routers may cache a built Agent per resolved manifest version/cache key so repeated hits skip rebuild. Tenant activate/rollback changes the active pointer and forces a fresh build. Prefer getting started for local iteration against bundled manifests.