agent-bridge
Allows delegation of tasks to Google Antigravity agents and integration with Antigravity for multi-agent workflows.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@agent-bridgeask coder to add input validation to src/api/users.ts"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
π ekip
Make your coding agents work as a team.
A vendor-neutral coordination hub that lets Claude Code, Google Antigravity, and any headless CLI agent delegate tasks to each other and share context β droppable into any project.
plan β debate β code β review β audit β an Opus architect, a Sonnet
reviewer, and a Gemini coder shipped a feature together in 5m39s,
unattended, using this hub.
π»π³ HΖ°α»ng dαΊ«n tiαΊΏng Viα»t
Why
Coding agents are getting great β but they work alone. The tools that do connect them are one-way ("use agent B as a tool inside agent A") or heavy (tmux supervisors, Python stacks). ekip takes a different shape:
Symmetric peers. No agent is the boss. Everything flows through one hub, so either side can delegate to the other β including you, from the web app or CLI.
A shared blackboard. Headless runs are one-shot; context survives on a key/value blackboard all agents read and write (
plan.v1,review.round1, β¦).Only sanctioned surfaces. MCP servers + each vendor's official headless CLI (
claude -p,agy -p). No scraping, no automation around rate limits.Rules the hub enforces. Flows run stage by stage inside the hub, with gates and capped loops β not instructions an agent may forget.
npm-light. One package, two dependencies, a web app with no bundler, no build steps at runtime.
flowchart LR
subgraph hub["ekip hub Β· one per machine, or one per project"]
Q["task queue<br/>pending β claimed β done"]
B["context blackboard"]
D["dispatcher + watchdog"]
end
CC["Claude Code"] <-- MCP --> hub
AG["Antigravity"] <-- MCP --> hub
YOU(["you Β· web app Β· CLI"]) --> hub
D -. "spawns headless<br/>claude -p / agy -p / any CLI" .-> W["one-shot worker runs"]
W -- MCP --> hubRelated MCP server: agent-comm
Quickstart
npm install -g @swtiit/ekip # the installed command is `ekip`
ekip start # runs the hub and opens the web appThat is the whole setup. ekip start works from any folder: it runs your own
hub β the crew you keep in ~/.ekip β and each conversation picks the folder
it works in, right in the app. Work you start without choosing a folder
happens in ~/ekip.
The hub is password-protected from the first run, and ekip start signs the
browser in for you; typing 127.0.0.1:4319 yourself asks for the token once
(ekip token prints it).
A project with its own crew β a different model per role, its own budget, its own flows β keeps the old shape:
cd /any/project
ekip init # writes ekip.config.json + prints the MCP snippets to paste
ekip start # this project's hubinit prints exactly what to paste into each agent (Claude Code's
.mcp.json, Antigravity's global config β including the permission grants
headless runs need, and the agent token line to export). Then, from any
connected agent or your own terminal:
ekip run claude-coder "Add input validation to src/api/users.ts"
ekip flow code-review "Add input validation to src/api/users.ts" # coder β reviewer, gatedtask 54d00e94 β conductor Β· chat: http://127.0.0.1:4319/chat/54d00e94β¦
21:39:00 β working conductor Feature pipeline: slugify
21:39:57 β done planner Plan slugify implementation (51s)
β Plan stored at slug1.plan.v1: NFD-decompose + Mn-stripβ¦
21:41:29 β done critic SCORE:93
21:42:06 β done agy Implement slugify.py + tests (30s)
β Self-verified: ALL TESTS PASSED
21:44:30 β done conductor Feature pipeline: slugify (5m39s)
ββ DONE ββ Β· auditor verdict: SHIPDay to day it is three habits: a small, clear task goes straight to a
coder; a change that matters runs the code-review flow; vague work
goes to the conductor, which splits it up. Each conversation is pinned to
the folder it started in, and each request has a budget (20 runs, 120 minutes
by default), so nothing runs away with your quota while you are not looking.
How a delegation works
sequenceDiagram
participant A as agent A
participant H as hub
participant B as agent B (spawned)
A->>H: bridge_delegate(to: B)
H->>H: task created (pending)
H-->>B: dispatcher spawns B's headless CLI
B->>H: bridge_claim(task_id)
Note over B: does the work<br/>reads/writes the blackboard
B->>H: bridge_post_result(done, artifacts)
A->>H: bridge_wait(task_id)
H-->>A: final task stateEleven MCP tools cover the whole protocol: bridge_delegate, bridge_claim,
bridge_post_result, bridge_wait, bridge_cancel, bridge_say,
bridge_thread, bridge_task_get, bridge_list_tasks, bridge_context_set,
bridge_context_get. Full contract in PROTOCOL.md.
Three ways to watch and drive it
The hub serves one web app at http://127.0.0.1:4319. It follows the hub's
reporting language, so a crew set to Vietnamese gets a Vietnamese interface.
View | What you get |
Chat | Conversations on the left, grouped by the project folder each one works in (pick the folder before you send β recent folders or a built-in folder browser; agents then run inside it and read its |
Board | A kanban by state (queued, working, done, failed and stopped) with per-agent filters and search. Click a card for its request, result, model, tokens, cost, receipts and log. The blackboard sits alongside |
Guide | Diagrams of how the hub works, the life of a task, hand-offs, flows, and how to read cost β with your live crew |
Settings | Reporting language (what agents and the hub write) and interface language β the app ships English and Vietnamese, chosen per browser β and each member's name, job, model (live lists where the vendor offers one), effort, parallelism and auto-launch β all saved as you change them. Plus the hub's limits, the folder guard, billing, and the snippet to connect another agent |
An agent that is working lights its tally β the red lamp a camera shows while
it records β everywhere it appears. βK jumps to any view, conversation or
agent. Light and dark follow the system, with a toggle in the header.
And two more ways in:
Surface | What you get |
CLI |
|
HTTP API |
|
Flows: pipelines the hub enforces
A conductor following a written pipeline can skip a gate or loop forever. A flow moves those rules into the hub: it hands each stage to one role, checks the result at a gate, sends the work back with the feedback when the gate isn't met, and stops for good when the rounds run out.
{
"name": "code-review",
"label": { "en": "Code, then review", "vi": "Code rα»i review" },
"steps": [
{ "id": "code", "agent": "claude-coder",
"prompt": "{{input}}\n\nReview findings to fix (empty on the first round):\n{{feedback}}" },
{ "id": "review", "agent": "reviewer",
"prompt": "Review the changes for: {{input}}\n\nReport: {{prev.code}}",
"gate": { "startsWith": ["APPROVE"] },
"onFail": { "goto": "code", "maxRounds": 2 } }
]
}Built in:
code-review(above) andfeatureβ plan β critique (SCORE β₯ 90, 3 rounds) β code β review (3 rounds) β audit (SHIP).Add your own as JSON in
.ekip/flows/(project) or~/.ekip/flows/(machine). Prompts get{{input}},{{feedback}},{{prev.<step>}},{{round}}and{{run}}(a per-run key for the blackboard). Gates match a score (pattern+min) or an opening word (startsWith).Run one from the Chat recipient picker,
βK,ekip flow <name> <input>, orPOST /api/flows/run. Every stage is a child task in one conversation, and each gate verdict (passed, back to a stage, stopped) is a line in it. A flow that names a role your crew lacks is listed with the reason and refused.
The role library behind it:
examples/roles/ β standing "role skills" (conductor, planner, critic, coder, reviewer, auditor). Point an agent's
promptFileat one and every spawn carries its persona, checklists, and output contracts.coder.mdserves both the Claude and the Gemini coder β same craft, different model and permissions.examples/feature-pipeline.md and examples/mini-pipeline.md β the same pipelines written as conductor scripts, for crews that prefer an agent to drive.
Who should get the work (measured)
One small task (a slugify helper with tests, graded on 8 hidden cases β
every route passed 8/8):
Route | Wall time | Runs | Claude list price |
Straight to | 49s | 1 | $0.27 |
| 122s | 2 | $0.30 + Gemini quota |
| 114s | 2 | $0.62 |
Small, clear work is cheapest sent straight to a coder. Having Claude review
Gemini's work does not save Claude quota β the review costs about as much as
doing it. A conductor adds a full run; it pays off on vague work that needs
splitting, while code-review is the cheaper way to make review mandatory.
Configuration
ekip.config.json β optional, and only when a project wants its own crew:
{
"project": "my-project",
"host": "127.0.0.1",
"port": 4319,
"agents": [
{ "name": "planner", "adapter": "claude",
"label": "Planner",
"description": "Researches the repo and writes the plan. Does not write code.",
"args": ["--model", "claude-opus-4-8", "--effort", "high"],
"promptFile": ".ekip/roles/planner.md" },
{ "name": "gemini-coder", "adapter": "antigravity",
"label": "Coder Β· Gemini",
"description": "Writes and edits files. Cannot run shell commands.",
"args": ["--model", "Gemini 3.6 Flash (High)"] },
{ "name": "codex", "adapter": "command",
"command": "codex", "args": ["exec", "{prompt}"] },
{ "name": "me", "adapter": "claude", "spawnable": false }
],
"maxDepth": 6,
"maxConcurrent": 4,
"watchdog": { "pendingTtlSeconds": 600, "claimedTtlSeconds": 3600 },
"budget": { "runs": 20, "outputTokens": 0, "minutes": 120 },
"retention": { "days": 14 }
}Machine defaults: once a project's cast feels right, run
ekip init --globalthere β it saves the agents and role files to~/.ekip/. Every futureekip initmaterializes that cast (and wires.mcp.json) automatically, so a new project is justinit && serve. Project files always win over machine defaults, field by field; rolepromptFiles resolve in the project first, then~/.ekip/roles/by filename.nameis the address,labelanddescriptionare the meaning. Agents hand each other work byname, so keep it short and stable.labelis what people see in the app;descriptionsays what the member is for β it is shown in the app and told to every spawned agent as part of a crew roster, so a conductor picks the right member from what each one does rather than from its name. Both are editable in Settings, which also shows each role brief.Checking a model id: Claude Code has no list-models command, so the only honest check is to run one. Settings has a Check button next to each Claude member (and
ekip models --check <id>,ekip models --refreshfor the aliases): it runs a one-word task with the id and reports what it really resolved to βsonnet β claude-sonnet-5β or why it was refused. The cost is a fraction of a run (measured: $0.06 on Haiku, ~$0.25 on Opus). Resolved aliases and ids that worked are remembered in~/.ekip/.Model-per-role: register the same adapter several times with different
--modelargs β delegating to a name picks a model. The Settings view edits these live (applies to the next task, and writes the config file). Model lists come fromagy modelsfor Antigravity β read live, because the names move between releases β and for Claude, which has no list-models command, from the aliases, your account's cached options, and models the hub has seen running here.spawnable: falseregisters an agent that polls (bridge_claim) instead of being auto-launched β e.g. a session you drive interactively.maxConcurrentcaps how many workers run at once per folder (default 4) and per agent within a folder ("maxConcurrent": 1on an agent entry);maxConcurrentTotalis the ceiling across all folders (default 8). Delegations past a cap queue and launch FIFO as slots free β so a runaway conductor can't fork ten Opus runs into your quota, and a busy project doesn't stall another.Folders. Each conversation works in the folder it was started in, and each folder has its own blackboard.
folderGuard(defaulttrue) tells every run its folder and, for Claude runs, adds a PreToolUse hook that checks file, search and shell calls β field-tested: without it, a headlessclaude -pread and wrote a sibling project freely. The hook reads paths out of commands, so it stops honest mistakes but not a determined bypass ($HOME/β¦, a symlink, a decoded script); treat it as a guard rail. Antigravity has no hook, so on macOS Gemini runs are started under the OS sandbox (sandbox-exec), which the kernel enforces: writes in your home go only to the folder and to agent state/caches (~/.gemini,~/.cache,~/.npm,~/Library/Cachesβ¦) β not shell startup files, LaunchAgents or other projects; reads of other home folders and of credentials (~/.ssh,~/.aws,~/.netrc,~/.npmrc, gh/docker/kube configs, Claude's files, shell history, browser profiles, Mail) are refused. The keychain file stays reachable because agy signs in through it. Field-tested with real agy runs. Set"sandbox": trueon any agent (including Claude, for a hard boundary) to confine it the same way;"sandbox": falseturns the Antigravity default off. Other platforms get the instruction only.One editor per folder. Members that edit files β
"writer": true, or inferred: Antigravity, or Claude withacceptEdits/bypassPermissionsβ never run two at once in the same folder (writersPerFolder, default 1;0= no limit). The second one queues with "another agent is editing this folder", so two coders can't overwrite each other; read-only members run alongside.budgetcaps what one request may spend β a message you send (with everything agents hand out from it), a flow run, or a top-level delegation β in worker runs, output tokens and minutes (defaults: 20 runs, no token cap, 120 minutes;0turns a limit off). Minutes count from the first run launched, so time queued or waiting for a person is free. The built-in flows carry their own (code-review4 runs/45 min,feature13/90). On a subscription these are what drain your plan. At a limit the hub refuses the next run with the reason in the conversation; running out of minutes also stops work in flight. Tokens are known only once a run reports, so a token cap stops the next run. A person's follow-up starts a fresh budget. A flow file may carry its ownbudget, andPOST /api/delegateaccepts one per request. Settings edits the hub default; the conversation header shows used/limit.retention.daysdrops finished conversations and their spawn logs after that many days (default 14;0keeps everything). A conversation goes as a whole, only when every task in it is finished and older than that β a recent follow-up keeps its history.mcpSessionsbounds the MCP sessions the hub keeps (each run opens one):max(default 256; the least recently used closes to make room) andidleMinutes(default 30). A closed session's client gets 404 and opens a new one.agents[].cwdruns a member in a fixed folder when a conversation doesn't pick one.watchdogtakespendingTtlSeconds(600),claimedTtlSeconds(3600),sweepIntervalSeconds(30) andenabled.language(e.g."Vietnamese") tells every spawned agent to write its notes, hand-offs and results in that language, and the hub writes its own notices (queued, stopped, failed, gates, budgets) in it too β code, paths and commands are untouched. Settings has a picker for it.promptFileprepends a markdown role to every spawn of that agent.The
commandadapter plugs in any CLI with{prompt},{hubUrl},{taskId},{agent},{depth}templating β no code required.Project-level knowledge (conventions, lint, CI) belongs in each tool's native files β
CLAUDE.md/.claude/skills/andAGENTS.mdβ which spawned runs pick up automatically.
Security
Anything that can reach the hub can launch agents that edit files, so:
The hub listens on
127.0.0.1. State-changing API and MCP requests must sendContent-Type: application/jsonand, when a browser sends an Origin, come from the hub itself β a web page on another site can't drive it. The Host header must be one of the hub's own addresses (DNS rebinding).The hub's records live outside the project. Tasks, conversations, the blackboard and spawn logs go to
~/.ekip/projects/<project>-<hash>/, not into the repo. A run working in the project that hosts the hub would otherwise read every conversation of every folder this hub has served, and could edit the hub's own config; out there the folder guard and the sandbox keep it out. An older layout is moved on the next start, and the project's.ekip/rolesand.ekip/flowsβ yours to write and commit β stay put.Two credentials, generated on first use and kept in
~/.ekip/auth.json(readable only by you;ekip tokenprints them, delete the file to roll them):yours opens the HTTP API and MCP. The web app asks for it once and keeps it in an HttpOnly cookie;
ekip uiopens the app already signed in; the CLI uses it automatically.the agent token is what spawned runs get, and it is accepted on
/mcponly. So a run that a file talks into something can still only use the bridge tools, inside the limits the hub puts on its own task β it cannotPOST /api/delegateto start work in another folder. Hand it to an agent you drive yourself withexport EKIP_AGENT_TOKEN=β¦;ekip initwrites that header into.mcp.json.EKIP_TOKEN/EKIP_AGENT_TOKENortoken/agentTokenin the config override them;"openAccess": trueturns tokens off entirely (then anything on the machine can drive the hub).
A hub told to listen beyond loopback refuses to start without a token.
Each run proves who it is. The hub gives every worker it launches a secret run key (in its instructions, its environment, and β for Claude β an MCP header). Only that key claims the task, so another session can't grab a task and post a fake "APPROVE" before the real reviewer does; queued tasks can't be claimed ahead of their run, and polling can't take work meant for a member the hub launches. A claimed task is reported only by its run while connected, and a reported result can't be replaced.
A run's hand-offs stay attached. When a run calls
bridge_delegate, the hub links the sub-task to that run's task β same folder, thread, budget and depth β and refuses a parent outside it.Known limit:
openAccess: truegives that up β anything on the machine, including a run, can then drive the hub through the HTTP API.
Cost on a subscription vs an API key
Claude Code reports each run's tokens and total_cost_usd; ekip records both
(the dollar figure is list price Γ tokens, checked to the micro-dollar). What
that figure means depends on how claude is signed in:
Pro/Max subscription (
claude auth statussays claude.ai): runs draw on your plan's limits and cost nothing per token. ekip detects this and hides dollar amounts β tokens and time stay β unless you switch them on in Settings.ANTHROPIC_API_KEYin the hub's environment:claude -pbills the API for real, and the app shows the money with a warning.
Token counts lead with output tokens; cache reads (0.1Γ price, often the bulk) are shown separately so a run doesn't look ten times bigger than it is. Antigravity reports no tokens, only time.
Letting spawned agents edit files
Out of the box a spawned run can only talk to the bridge. For real coding (all field-tested):
Claude Code: add
"--permission-mode", "acceptEdits"to the agent'sargs; allowlist specific commands via--allowedTools "Bash(npm test:*)".Antigravity: model names move between releases (
agy modelslists what the installed binary accepts β a stale name exits 1 before the run starts, and ekip surfaces that line on the failed task). Headless agy soft-denies anything needing a prompt, and a single denial kills the whole run. Grants live in~/.gemini/config/config.jsonunderuserSettings.globalPermissionGrants.allow:"mcp(ekip/*)"for the bridge tools,"write_file(*)"for a coder (scope tighter if you like), plus"command(<cmd>)"for each command it may run. The adapter always passes--add-dir <cwd>β without it, headless runs write into agy's scratch directory instead of your project.
When workers die (and the quota question)
Spawned agents die silently more often than you'd hope β quota exhaustion
(Claude's "session limit", agy's silent 429 exit), permission denials,
missing binaries. The hub keeps the worker's process handle: the moment it
exits without having posted a result, the task fails within seconds,
with the exit code and the reason grepped from the spawn log β so the
web app tells you worker exited (code 0) without claiming the task β spawn log hints: "You've hit your session limitβ¦" instead of hanging.
A watchdog remains as the safety net for workers that are alive but wedged
(TTL on pending/claimed, then the worker is killed), and ekip cancel <task> (or bridge_cancel from any agent) stops a task and everything
delegated from it, killing the whole process tree.
Stopping the hub (Ctrl+C) stops the workers it started and marks their tasks failed with the reason, so nothing keeps editing with nobody listening. On the next start, work that was queued launches again, a flow that was mid-run is failed with "the hub restarted" (its runner lived in the old process), and the watchdog counts a run's streamed tool calls as signs of life, so a long run that is still working isn't reaped. State is written atomically; an unreadable state file is kept aside instead of overwritten.
Neither vendor exposes remaining quota programmatically today, so the bridge surfaces quota problems post-mortem β and the pipeline templates carry spawn estimates (best case 6, worst case ~12 per feature run) so you can budget.
Testing
npm test # 316 end-to-end cases, no LLMs involved
npm run test:ui # 24 browser checks in headless Chrome (uses the installed Chrome)
npm run soak # stability: bursts of work, cancels, a hub restartBoots a real hub on a scratch port and exercises the HTTP API, all 11 MCP
tools, the conversation layer (stream-json decoding via a mock claude,
threads, bridge_say), the dispatcher, permission/claim edge cases, folders and the
folder guard, access control and tokens, flows (gate retry, round caps, cancel), budgets (runs, tokens, time), one editor per folder, result ownership, the OS sandbox (macOS), fail-fast on worker
exit, watchdog reaping (and worker kill), cancellation with process-tree
kill and cascade, maxConcurrent queueing, retention pruning, loop-guard,
concurrency (parallel claims), crash-safety (missing binaries), and the CLI
as a subprocess. The same suite runs in CI on Linux and macOS with Node 22 and 24, plus Node 26 on Linux.
Each suite cleans up its scratch folders when everything passes, and keeps
them (saying where) when something fails; KEEP_TMP=1 always keeps them.
npm run soak is the stability harness: rounds of mixed work (healthy, slow,
crashing, missing-binary and hanging workers) fired in bursts, cancels
mid-flight, and a hub restart β asserting that every task reaches a terminal
state, the concurrency cap holds, state and conversations survive the
restart, and no worker process is left behind. SOAK_ROUNDS and SOAK_BURST
turn up the pressure.
FAQ
Does this violate any provider's terms? It uses only documented surfaces: MCP servers and official headless CLIs, each authenticated with your own accounts. It never proxies one model through another, trains on outputs, or works around rate limits.
Do both apps have to be open? No. Only the hub runs persistently. The receiving agent is spawned headless on demand and exits when done; the sender is whatever you're already working in (or the web app).
How do I add an agent that isn't Claude or Antigravity? Usually zero
code: the command adapter + an args template. Bespoke behavior = one
adapter file implementing spawn + mcpConfigSnippet.
What if two agents delegate to each other forever? Every task carries a
delegation depth; the dispatcher refuses past maxDepth (default 6), and
flows cap every loop with maxRounds. maxConcurrent bounds the
blast radius in the meantime, and ekip cancel stops a whole tree.
Prior art & positioning
One-way bridges that expose agy as a tool inside Claude Code exist (agy-bridge, claude-to-agy), and AWS Labs CAO orchestrates CLIs under a tmux supervisorβworker hierarchy. ekip occupies the gap: symmetric peer delegation + a shared blackboard, per-project, npm-light.
License
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP Server for an Agent Task Marketplace
An MCP memory server. One memory your agents share β across models, devices and apps.
MCP server for building and testing AI agents with multi-model experimentation and insights.
Control plane for autonomous software labor. Agents claim objectives over MCP with audit trail.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceMCP server for multi-agent collaboration enabling AI agents to communicate, delegate tasks, and share artifacts across clients and machines with federation support.12 npm1MIT
- AlicenseNot gradedqualityDmaintenanceMCP server that enables AI coding agents to communicate, share state, and coordinate work in real time via MCP tools or REST API.123 npm5MIT
- AlicenseAqualityCmaintenanceAn MCP server that turns independent AI agents into a coordinated engineering team with shared task board, context, review loop, and enforced plan-implement-review-iterate workflow.24MIT
- AlicenseNot gradedqualityDmaintenanceA self-hosted MCP server enabling multiple AI coding agents to share state, preserve context across sessions, and coordinate with each other.28 npmApache 2.0