Quick Start
1
Default (single-tenant)
Use the module-level functions — no
registry= kwarg needed. This is what almost every user wants.2
Scoped (multi-tenant / multi-embedding)
Construct an
AgentRegistry() per tenant and pass it via the registry= kwarg. Two AgentOS gateways in the same interpreter can now hold isolated agent sets.3
Bind a per-tenant registry to a mounted FastAPI app
Passing The override is per FastAPI app instance, so two
registry= to register_agent(...) scopes the free functions, but the mounted router’s route handlers resolve their registry through Depends(_registry_dependency). Override that dependency so /agents, /agents/{id}, and /agents/{id}/invoke serve your registry instead of the process-global one.AgentOS gateways in the same interpreter now serve their own agent set through /agents, /agents/{id}, and /agents/{id}/invoke — not a shared list.How It Works
Every invocation resolves throughresolve_session_agent(agent_id, session_id, *, registry=None), which clones the registered template per request so concurrent callers never share mutable conversation state. The invoke handler passes in whatever Depends(_registry_dependency) resolved to, so a per-app override reaches the resolver.
unregister pops the id atomically under a lock (dict.pop), so a concurrent unregister can’t race between the membership check and the delete — the previous split check-then-delete returned uncaught 500s on concurrent deletes, which is the reason the class exists.
Configuration Options
AgentRegistry methods:
Module-level functions (backward-compatible):
Best Practices
Prefer the default registry unless you run multiple tenants
Prefer the default registry unless you run multiple tenants
The module-global is already thread-safe, and the
registry= kwarg is the escape hatch, not the default path. Use plain register_agent(agent_id, agent) / get_agent(agent_id) for single-tenant setups.Give each embedded server its own AgentRegistry
Give each embedded server its own AgentRegistry
Two
AgentOS gateways sharing the module global will step on each other’s agent ids. Construct one AgentRegistry() per gateway and thread it through your register_agent(...) calls.When embedding the router, override _registry_dependency
When embedding the router, override _registry_dependency
Just calling
register_agent(..., registry=my_reg) isn’t enough — the router’s route handlers resolve their registry via Depends(_registry_dependency). To serve your registry through the API, add:_registry_dependency is an override key, not a helper you call from user code — its name starts with _ on purpose.Registry holds templates, not live conversations
Registry holds templates, not live conversations
Every invocation goes through
resolve_session_agent, which clones the template per request via clone_for_channel. Do not stash mutable state on the registered agent expecting it to survive across calls.Related
AgentOS Chat Session Isolation
Session isolation cloning path
Serve Agents Auth
Surface where this registry is invoked

