Federation¶
Federation is two AiFlow deployments delegating tasks to each other over MCP, as peers. Each stays fully separate: its own database, its own credentials, its own audit log. Nothing is merged.
This is the same machinery as AiFlow as an MCP server and Orchestrator MCP servers, pointed at another AiFlow rather than a third-party tool server.
Linking two deployments¶
Say a support hub wants to delegate diagnostic tasks into a client deployment.
On the client (the receiving side):
- Create an API key (Settings -> API keys) with the
mcp:orchestratescope. Leave it unscoped to any single agent. - Give the raw key to whoever administers the hub.
On the hub (the calling side):
- Add an Orchestrator MCP connection (per-Orchestrator, or the shared
pool) whose URL is the client's
https://.../api/v1/mcp/and whose bearer token is that key. - That Orchestrator can now call the client's
delegate_task_to_orchestratortool like any other MCP tool.
For a two-way relationship, repeat the steps with the roles reversed.
Recording the relationship¶
Settings -> Federation (a licensed feature, see
Licence limits) is a directory of the
remote deployments this one is linked to: a name, the remote base URL,
whether the remote is a parent, a child, or a peer, free
notes, and, for an inbound relationship, the mcp:orchestrate API key
the remote presents when it calls in. An admin can see the "org chart" at
a glance and audit it. The outbound MCP connection is still managed on its
own screen.
Governing inbound calls¶
Attaching an API key to a link makes that link the unit three controls apply to. They cover only a call arriving from another instance, not a first-hop call from your own trigger, Agent, or MCP client.
- Allow-list. Set
FEDERATION_INBOUND_ALLOWLIST_ENABLED=trueand a federated delegate call is accepted only from a key bound to an enabled link. Left off (the default), anymcp:orchestratekey may still call in. - Rate limit. Inbound federated calls on one link are capped at
FEDERATION_INBOUND_RATE_LIMIT_PER_MINUTE(default60) per minute; calls over the ceiling are refused with a plain error. - Circuit breaker. A link that stays over the ceiling for
FEDERATION_CIRCUIT_BREAKER_TRIPSrefusals in a row (default5) is disabled automatically, an audit entry is written, and afederation_link.auto_disabledwebhook fires. The Federation screen shows an "Auto-disabled" badge; flip the link's switch back on to clear it once the cause is understood.
The loop guard¶
A delegated task that routes work back to where it came from would, left alone, bounce between the two deployments forever, running a real, separately-billed model completion on each side every time.
delegate_task_to_orchestrator prevents that. Every federated delegation
carries two headers, propagated onward by every outbound MCP call the
delegated run makes:
X-AiFlow-Federation-Hops, a counter incremented at each instance boundary. A deployment refuses a call once it exceedsFEDERATION_MAX_HOPS(default3).X-AiFlow-Federation-Trace, a single id for the whole chain. A deployment refuses a trace it has already handled.
Either check tripping comes back as a normal tool error result naming a federation loop, not a hang. The Agent at the top of the chain can then say something sensible to the caller.
Note that a hub -> client -> hub round trip inside one delegated task is refused too: within one chain, a deployment is entered once. If a client genuinely needs to escalate back to the hub, that is a new task the client starts, with its own fresh trace.
The guard is a cooperative convention: it works because every AiFlow in the chain forwards the headers. It stops the realistic mistake, both directions wired up by two well-meaning admins. It cannot stop a deliberately modified peer that strips the headers.