-
Notifications
You must be signed in to change notification settings - Fork 16
Registry
The registry (crates/tinyagents-registry/) is the named capability catalog:
every model, tool, graph, agent, router, and reducer is registered under a
name, and .rag source binds to those names rather than to Rust types. It is
what a .rag blueprint's model/tool/subgraph references resolve against.
The registry is explicit, not a hidden global — you own one per application, test, tenant, or workspace. It does not execute graph nodes or call providers; it answers "which capabilities exist, under what names, and is this name allowed?"
Cargo feature: tracing only (no default features).
Three submodules:
-
component— identity and discovery types. -
capability— the name-addressableCapabilityRegistry. -
catalog— the offline model catalog (prices, context windows, capabilities). -
router—ModelRouter, a workload-alias layer over named models.
-
ComponentId(String)— a stable identifier, a newtype over the registered name (e.g."gpt-4o","lookup_user"), not a Rust type path. -
ComponentKind— partitions the namespace: lookups, duplicate detection, aliasing, and discovery are all scoped by kind, so(Model, "x")and(Tool, "x")are independent entries. Variants:Kind Stores Executable? ModelArc<dyn ChatModel<State>>yes ToolArc<dyn Tool<State>>yes GraphBlueprint(a compiled.raggraph)serializable value AgentArc<dyn HarnessAgent>yes Routername-only descriptor no Reducername-only descriptor no Storename-only descriptor no Scriptname-only descriptor for a host-provided scripted node no Middlewarename-only descriptor no Checkpointername-only descriptor no TaskStorename-only descriptor no Listenername-only descriptor no -
ComponentMetadata { id, kind, description, tags, aliases }— discovery metadata. Every registration records one, even the name-only kinds (where description and tags start empty); it is the source of truth for presence.
CapabilityRegistry<State = ()> is the name-addressable catalog, generic over
the application State because models and tools are generic over it.
Registered agents are state-decoupled — a HarnessAgent receives a mapped
prompt, not the registry's State — so the agent map does not depend on the
State generic.
It is distinct from the harness's per-run ModelRegistry and ToolRegistry
(executable stores for a single harness). CapabilityRegistry is the catalog
that declarative source is validated against; to_model_registry() /
to_tool_registry() build a harness registry out of it.
let mut reg = CapabilityRegistry::<()>::new();
reg.register_model("gpt-4o", model)?; // duplicate name -> error
reg.register_tool(tool)?; // keyed by Tool::name()
reg.register_graph_blueprint("triage", blueprint)?;
reg.register_agent(agent)?; // keyed by HarnessAgent::name()
reg.register_router("route_by_intent")?; // name-only descriptor
reg.register_reducer("append_messages")?; // name-only descriptor
reg.alias(ComponentKind::Model, "fast", "gpt-4o")?;-
register_*fails with a duplicate-component error if the(kind, name)pair already exists;replace_model/replace_tool/replace_graph_blueprint/replace_agentoverwrite while preserving any richer metadata already attached. -
register_descriptor(kind, name)backs the name-only kinds. -
alias(kind, alias, target)declares an alternate name; it validates the target exists and the alias is free.
Looking things up: model(name), tool(name), graph_blueprint(name),
and agent(name) resolve a name (or one alias hop) to a live handle or
blueprint. has(kind, name) answers presence, names(kind) lists canonical
names, and names_including_aliases(kind) lists canonical names and aliases
— the set a .rag source may reference. metadata(kind, name) returns the
ComponentMetadata.
Handing off to the runtime: to_model_registry() builds a harness
ModelRegistry from the registered models, binding alias names to the same
handle. to_tool_registry() builds a harness ToolRegistry (tools are keyed
by their own Tool::name(), so tool-level aliases are not propagated — a
tool is always invoked under its canonical name). capability_resolver()
builds the language layer's CapabilityResolver, the bridge to .rag.
CapabilityRegistry<State> also implements
tinyagents_language::capability_resolver::CapabilitySource and
tinyagents_graph::subagent_node::AgentRegistry, which is what lets a .rag
blueprint resolve capability names and lets a SubAgentNode resolve a
registered Agent by name.
snapshot() returns a serializable RegistrySnapshot, sorted by
(kind, name). It enumerates both components and every alias as
AliasBinding { kind, alias, canonical }.
let mut reg = CapabilityRegistry::<()>::new();
reg.register_model("gpt-4o", model)?;
reg.alias(ComponentKind::Model, "default", "gpt-4o")?;
let snapshot = reg.snapshot();
assert_eq!(snapshot.aliases[0].alias, "default");
assert_eq!(snapshot.aliases[0].canonical, "gpt-4o");
assert_eq!(snapshot.aliases[0].kind, ComponentKind::Model);diagnostics() returns RegistryDiagnostics the registration-time duplicate
check cannot catch alone: an alias that shadows a registered component's
name, a dangling alias pointing at an unregistered name, and a name reused
across different kinds (legal, since kinds partition the namespace, but
flagged for audits — the diagnostic message names the offending kinds).
let mut reg = CapabilityRegistry::<()>::new();
reg.register_model("shared", model)?;
reg.register_router("shared")?; // legal: a different kind
let diags = reg.diagnostics();
assert_eq!(diags[0].name, "shared");
assert!(diags[0].message.contains("multiple kinds"));CapabilityResolver::from_registry(reg) snapshots
names_including_aliases for every kind into allow-lists (models, tools,
subgraphs, routers, reducers). When a .rag blueprint names a model, tool,
subgraph, router, or reducer, the compiler checks it against these
allow-lists — an unknown reference is a compile error before anything runs.
Because graphs are registered as Graph components, a blueprint can
reference another blueprint by name as a subgraph.
flowchart LR
Rust[Rust: register_* by name] --> Reg[CapabilityRegistry]
Reg -->|names_including_aliases| Res[CapabilityResolver]
Rag[".rag source"] -->|references names| Res
Res -->|validated| Graph[Graph + Harness runtime]
See Expressive Language (.rag).
ModelRouter maps a workload alias (chat-v1, vision-v1, ...) onto a
WorkloadRoute { alias, model, requires: CapabilitySet, fallbacks }. It is a
declarative layer above the named model registry: route(alias) /
target_model(alias) resolve an alias to a concrete registered model name,
required_capabilities(alias) returns the capability gate, and
fallback_policy(alias) returns an ordered same-family fallback chain. A host
uses this to let application code ask for "the model for this workload" while
keeping the concrete model swap in one place.
The model catalog is an offline snapshot of provider model metadata, not a
live source of truth. It gives deterministic behavior for cost estimates,
context-window checks, and capability gating without a network call. A
checked-in snapshot (crates/tinyagents-registry/model-catalog.snapshot.json)
is compiled into the crate.
-
ModelCatalog::seed()loads the bundled snapshot;from_json/from_snapshotload a custom one.get(provider, model_id)andget_by_model_id(model_id)resolve an entry by id or alias;snapshot()exposes the rawModelCatalogSnapshotandmodels()the full entry slice. -
ModelCatalogSnapshotcarriesschema_version,snapshot_id, provenance, and themodelslist. -
ModelCatalogEntrydescribes one model:provider,model_id,aliases, token limits,pricing, andcapabilities. -
ModelPricinggives per-token input/output prices plus cache-read, cache-creation, audio, and reasoning rates. -
ModelCapabilitiesis the feature matrix:streaming,tool_calling,parallel_tool_calling,json_schema,system_messages,vision,audio_input/audio_output,pdf_input,prompt_caching,reasoning.
Use a CapabilityRegistry to compile and validate .rag blueprints, to let
one agent or graph reference another by name instead of hardcoding it, to
power a discovery UI over available models/tools/graphs, or to hand a
curated, allow-listed set of models and tools to a harness. Use the model
catalog for offline cost or capability facts about a model.
- Architecture — how the crates fit together.
-
Graph Runtime — what registered
Graphblueprints become. - Expressive Language (.rag) — the language that binds against registered capabilities.
Provider-neutral agent harness and durable state-graph runtime for Rust.
Getting started
Concepts
Modules
Providers
Contributing