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.
Inputs
Section titled “Inputs”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).
Build steps
Section titled “Build steps”-
Validate — re-check schema + cross-field rules (single vs multi-agent, pattern registry kind, durable + checkpointer constraints).
-
System prompt — join soul (if enabled) +
system_prompt.base+inline. -
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; bindlist_skills/activate_skill/deactivate_skill/read_skill_file, which return a body only on activation. Withspec.skill_authoring.enabled, also bindcreate_skill,update_skillandsubmit_skill_feedback— before governance, so an approvals rule holds them. -
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. -
Sub-agents / local tools — multi-agent patterns build children; single-agent resolves
spec.toolsfrom the provider. Auto-inject memory / procedural /read_artifactwhen enabled — all before governance, so they are gated like any other tool.pattern: deepinjects plan tools before governance so they are gated like everything else. -
Governance pipeline (innermost → outermost on the call path):
secret masking → policies → command screening → content screening→ limits → guardrails → LLM judges → approvals → (artifact spill)See governance.
-
Pattern dispatch —
get_pattern(spec.pattern)from the open registry (react,deep,router,parallel,groupchat,reflect,plan_execute, plus any registered plugins). -
Durable wrap — when
spec.execution.mode: durable, wrap so invoke enqueues a fiber and returns a resume token.
Session + memory at build time
Section titled “Session + memory at build time”| 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 |
Caching
Section titled “Caching”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.