Skip to content
MeridFlow AiFlow v8.x • self-hosted

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):

  1. Create an API key (Settings -> API keys) with the mcp:orchestrate scope. Leave it unscoped to any single agent.
  2. Give the raw key to whoever administers the hub.

On the hub (the calling side):

  1. 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.
  2. That Orchestrator can now call the client's delegate_task_to_orchestrator tool 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=true and a federated delegate call is accepted only from a key bound to an enabled link. Left off (the default), any mcp:orchestrate key may still call in.
  • Rate limit. Inbound federated calls on one link are capped at FEDERATION_INBOUND_RATE_LIMIT_PER_MINUTE (default 60) 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_TRIPS refusals in a row (default 5) is disabled automatically, an audit entry is written, and a federation_link.auto_disabled webhook 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 exceeds FEDERATION_MAX_HOPS (default 3).
  • 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.