Quick Start
orx.yaml
- Python
- CLI
- A2A Server
Architecture
The Composer is built around three modular registries underbuilders/:
YAML Schema
defaults
Global settings inherited by all agents.
models
Named model configurations. Agents reference them by name instead of repeating inline config.
provider, name, and temperature is forwarded directly to the LangChain model constructor (e.g. max_tokens, api_key, base_url, timeout, etc.).
Agents reference models by name:
model: for one-off overrides:
tools
Named tool definitions referenced by agents. Every tool entry must set exactly one of function, mcp, builtin, agent, transfer, or custom.
skills
Named skill definitions, referenced by agents. Each agent that lists skills gets its own in-memory skill store with list_skills and load_skill tools.
Skills can be defined inline, loaded from a directory (Agent Skills Protocol), or fetched from a FastMCP server.
scan_skill_directory() and support the full 3-tier progressive disclosure model with load_skill_resource for on-demand resource files. See Skills for details.
Agents reference skills by name:
agents
Flat dict of agent definitions. Agents reference each other by name.
Agent Types
| Type | Description | Required fields |
|---|---|---|
llm | LLM-powered agent with tool loop | instructions |
react | Structured Reason+Act agent | instructions (optional) |
sequential | Run sub-agents in order | agents |
parallel | Run sub-agents concurrently | agents |
loop | Repeat sub-agents until done | agents, max_iterations |
a2a | Remote agent via A2A protocol | url |
The composer’s schema validator enforces the Required fields column at YAML-parse time:
a2aagents must seturl.sequential/parallel/loopagents must set a non-emptyagentslist.
warnings.warn for fields that are silently ignored by an agent type (e.g. tools on a composite, model on an a2a, planner on non-LLM types). Running with -W error turns those into hard failures.Custom agent types registered via register_builder are exempt from both checks — they’re free to consume any field.main_agent
The entry-point agent name.
runner
Optional. Enables Composer.runner_from_yaml().
compaction is set, the Runner automatically summarizes old session events after each invocation based on character count (not event count). Uses the default model for LLM-based summarization. See Session Compaction for details.
server
Optional. Enables Composer.server_from_yaml() for A2A.
Identity, trust, and attestation
Three optional blocks wire the trust layer into the Runner: sign every emitted event, verify incoming ones against a policy, and audit the whole stream through an attestation provider. Every block is opt-in — leave them out and the Runner behaves exactly as before.Requires the auth extra:
identity: — Ed25519 signing key
Attaches a signing identity to every agent under the Runner. When set, every Event the tree emits is signed with Ed25519 over the canonical event payload (including prev_signature to form a hash chain), and verifiers downstream can prove the event hasn’t been tampered with.
trust: — signature verification policy
Installs TrustMiddleware on the Runner. Requires an identity: block (verification needs keys).
event.metadata["trust"] = {"verified": False, "reason": ...} so downstream consumers can flag them.
attestation: — claim issuance + audit log
Installs AttestationMiddleware on the Runner. Every event is appended to the provider’s audit log; notable actions (agent transfers, tool invocations) also produce typed claims.
noop— records nothing. Matches the default when noattestation:block is present.local— JSON-on-disk atpath, SHA-256 hash-chained, every entry signed with theidentity:key. Zero external deps.<dotted.import.path>— anything else is treated as an import path to a user-suppliedAttestationProvider. Plug in a vendor SDK, a blockchain anchor, or your own implementation.
Examples
Transfer Routing
Sequential Pipeline
Loop with Exit
Extending with Registries
Custom Agent Types
(name, agent_def, spec, *, helpers) where helpers provides:
helpers.resolve_model(agent_def)- merge agent/default model confighelpers.resolve_tools(agent_def)- resolve all tool referenceshelpers.build_agent(name)- recursively build a sub-agent by name
Custom Model Providers
openai, anthropic, google. Any unrecognized provider string is treated as a dotted import path to a custom BaseChatModel class.
Custom Builtin Tools
Custom tool types (register_tool_resolver)
The five built-in ToolDef shapes (function, mcp, builtin, agent, transfer) cover most needs — but if you need a whole new kind of tool (a webhook, an HTTP RPC, a proprietary bus), reach for the custom: field + a resolver.
Python API
| Method | Returns | Description |
|---|---|---|
Composer.from_yaml(path) | BaseAgent | Parse YAML and build the root agent (sync) |
Composer.from_yaml_async(path) | BaseAgent | Same, async |
Composer.runner_from_yaml(path) | Runner | Build a Runner with sessions + trust middleware |
Composer.runner_from_yaml_async(path) | Runner | Same, async |
Composer.server_from_yaml(path) | FastAPI | Build an A2A server app |
Composer.server_from_yaml_async(path) | FastAPI | Same, async |
Composer(spec).build() | BaseAgent | Public build hook for callers that need to mutate spec between construction and build |
Composer(spec).build_runner(root) | Runner | Wrap a built tree in a Runner |
Composer(spec).build_server(root) | FastAPI | Wrap a built tree in an A2A app |
| Registry function | Description |
|---|---|
register_builder(type, fn) | Add a custom agent type builder |
register_provider(name, cls) | Add a custom model provider |
register_builtin_tool(name, factory) | Add a custom built-in tool |
register_tool_resolver(type, resolver) | Add a new tool type accessible via tools: { custom: { type: ... } } |