bridge — AgentTeamsModule¶
Lightweight cross-framework compatibility bridges that preserve source canonical documentation. Unlike convert, which migrates a team into another framework's format, the bridge keeps the source canonical and emits a thin compatibility layer beside it; the CAI transport path is interop. Bridge-merge refreshes fit into the broader update lifecycle guide.
Source:
agentteams/bridge.py
Public Types¶
BridgeResult¶
Summary of bridge generation or bridge check run.
Fields:
written: written (or would-be-written) pathsskipped: skipped existing pathserrors: error messagesdry_run: whether writes were simulatedcheck_only: whether run was check modecheck_ok: bridge freshness verdictcheck_report_path: report path when check mode runsmanifest_missing(bool): in check mode,Truewhen the bridge manifest file does not exist at the expected path (defaultFalse)notices(list[str]): human-readable per-file notices accumulated during the run — e.g. merge-mode files skipped because they lack anAGENTTEAMS-BRIDGEfence (default empty)
Property:
success:Truewhen no errors and check passes (for check mode)
Public Function¶
run_bridge(*, source_dir, target_framework, output_root, source_framework=None, dry_run=False, overwrite=False, check_only=False, merge_only=False, emit_skills=True, host_features=None, description=None)¶
When subagent stubs are requested for a team under write_policy: "orchestrator-only" (read from the target's build-log, which fails closed when present but unreadable, or from description), it raises ValueError before any write (interop_write_policy.refuse_bridge_stubs). The stubs copy the source's tools.
Generate bridge artifacts or validate bridge freshness.
Args:
source_dir(Path): canonical source agent directory.target_framework(str): target runtime framework.output_root(Path): root where bridge artifacts are written.source_framework(str | None): optional source override.dry_run(bool): simulate writes.overwrite(bool): destructively overwrite existing target-framework entry files atoutput_root(CLAUDE.md,.claude/agent-team.md, etc.) and existing bridge-internal artifacts. Triggered by--bridge-refresh.check_only(bool): run freshness check only; no writes.merge_only(bool): non-destructive update of target-framework entry files. Bridge-internal artifacts underreferences/bridges/.../are always regenerated. For target entry files, only content inside<!-- AGENTTEAMS-BRIDGE:BEGIN <region> v=N --> ... <!-- AGENTTEAMS-BRIDGE:END <region> -->fences is re-rendered; content outside fences is preserved verbatim. Files lacking any bridge fence are skipped with notices inbridge-merge.report.md. With thebridge:copilot-vscode-to-claude:subagentshost feature, existing non-stub.claude/agents/*.mdfiles (native agent bodies) are kept rather than replaced by stubs. Triggered by--bridge-merge.emit_skills(bool): emit.claude/skills/recall/SKILL.mdand.claude/skills/code-recall/SKILL.mdskill templates (claude target only). DefaultTrue. Set toFalse(via--bridge-no-skills) if your team manages skills separately.-
host_features(list[str] | None): opt-in subselectors that gate additional emission paths. WhenNoneor[], default emission is unchanged. Recognised tokens (claude target):bridge:copilot-vscode-to-claude:subagents— emit per-agent stubs viabridge_subagents.bridge:copilot-vscode-to-claude:hooks— emit hook settings + guard viahooks_emit.bridge:copilot-vscode-to-claude:cache-split— emit cache-awareCLAUDE.mdviainstructions_splitin place of the default pointer file.bridge:copilot-vscode-to-claude:schedule— emit.claude/schedules.agentteams.jsonviaschedule_emit.bridge:copilot-vscode-to-claude:todo-projection— emit.claude/skills/todo-from-plan/SKILL.md(rendered byplan_steps_todo.render_skill).bridge:copilot-vscode-to-claude:parallelize— emit.claude/skills/parallelize-plan/SKILL.mdviaparallel_plan.render_skill.
Recognised tokens (goose target;
<source>is the detected/declared source framework, e.g.copilot-vscode): -bridge:<source>-to-goose:subagents— emit per-agent Goose recipe stubs viabridge_subagents_goose. -bridge:<source>-to-goose:mcp— wire the source project's declared MCP servers into the.goose/recipes/bridge-orchestrator.yamlrecipe.Tokens are parsed and validated by
host_features. CLI surface:--target-host-features TOKENS.
Returns:
BridgeResult
Raises:
FileNotFoundErrorwhen source directory is missing.ValueErrorfor unknown framework ids.
Artifacts¶
Bridge artifacts are generated in:
references/bridges/<source>-to-<target>/
Core files:
bridge-manifest.jsonagent-inventory.mdquickstart-snippet.mdentrypoint.mddomain-boundary.md— clarifies the memory-index vector-mode boundary vs project-level retrieval-integrator contracts.
Check mode also emits:
bridge-check.report.md
Merge mode also emits:
bridge-merge.report.md— per-file status: merged / skipped (no fence) / skipped (no rendered fence).
Claude target with emit_skills=True (default) also emits at output_root:
.claude/skills/recall/SKILL.md— wrapsagentteams --query-indexfor in-session retrieval. Not underreferences/bridges/...; lives in the consumer's.claude/skills/directory..claude/skills/code-recall/SKILL.md— wrapsagentteams --query-codefor in-session code/API index retrieval. Same location convention asrecall/SKILL.md.
Goose target emits these fenced entry files at output_root (regions
goose-bridge-entry/-hints/-readme):
AGENTS.md— repo-root pointer to the source inventory/quickstart. Shared multi-tool file (Cursor/Codex/Cline also read it) — see the warning below..goosehints—@AGENTS.mdintegrator so Goose's default context discovery loads the bridged brief..goose/README.md— bridge note.
Goose target also always emits (bridge-owned; not fence-scoped, regenerated on every run regardless of mode):
.goose/recipes/bridge-orchestrator.yaml— Goose recipe stub wiring thedeveloper(CLI) extension and, when thebridge:<source>-to-goose:mcphost-feature token is set, the source project's declared MCP servers.
Goose is supported as both a bridge source and target: any of copilot-vscode/copilot-cli/claude/canonical → goose, and goose → claude/copilot-vscode/copilot-cli. Only goose → goose is rejected (raises ValueError) as meaningless.
Notes¶
- Designed for runtime interoperability without full cross-framework regeneration.
- Hash-based freshness checks detect changed, missing, and newly added source files.
- Target entry files are emitted to help route users through source orchestrator-first flow.
Operator-Facing Helpers¶
rel_to_root(path, output_root) -> str¶
Source:
agentteams/bridge.py
Render a path relative to output_root when it lies inside it.
Bridge artifacts are committed, so an absolute path baked into one leaks the operator's
home directory and username. 1937cbc fixed this for bridge-manifest.json's
source_dir — one field, one file — leaving the sibling artifacts the same run writes
still absolute: agent-inventory.md's source-file column and
bridge-merge.report.md's per-file lines, across all three pairs. This is the shared
form so the three sites cannot drift again.
Returns: str — Relative to output_root, or unchanged when the path lies outside
it (a genuinely external path is information, not a leak).
Guarded by
tests/test_bridge_mode_safety.py::test_no_committed_bridge_artifact_contains_an_absolute_home_path,
which scans every file under references/bridges/ rather than the manifest alone.
skip_notice(count, *, merge_only) -> str¶
Source:
agentteams/bridge.py
Build the notice for target files the bridge left alone. The two cases are opposite in meaning and must not share advice.
Under --bridge-merge a skip is the contract: a target file with no
AGENTTEAMS-BRIDGE fence holds user-authored content, and leaving it untouched is the
entire reason merge mode exists. This notice previously recommended --bridge-refresh
in both cases — advising the operator to overwrite precisely the files that had just
been protected, and calling it "recommended when bridge state is incomplete or
stale", which is when the advice is most likely to be followed. That is the 2026-05-27
incident recorded in references/bridge-refresh-safety.md, still live in the tool.
Args:
count(int) — How many target files were skipped.merge_only(bool, keyword-only) —Trueunder--bridge-merge.
Returns: str — Under merge, explains the skip and warns against refresh;
otherwise offers merge first and gates refresh behind the mandatory Pre-Flight
reference.
Mode Selection Guidance¶
| Situation | Use |
|---|---|
| First-time bridge generation for a project | --bridge-refresh (or --bridge-from with no mode flag, on a project that has no target entry files yet) |
Re-running after source agents changed; consumer's CLAUDE.md/.claude/* have been customized |
--bridge-merge — preserves customization outside the bridge's fenced regions |
| Re-running with no consumer customization to preserve | Either --bridge-refresh or --bridge-merge works; --bridge-merge is the safer default |
| Verifying source has not drifted from manifest | --bridge-check |
Warning:
--bridge-refreshunconditionally overwritesCLAUDE.mdand.claude/*at the consumer'soutput_rootwith terse stubs. If your team has rich entry files, use--bridge-mergefor refreshes. Consumer-managed sections should live outside the<!-- AGENTTEAMS-BRIDGE:BEGIN ... -->fences so the merge logic preserves them.Goose target — extra caution:
AGENTS.mdis a shared, multi-tool standard file read by Cursor, Codex, Cline, and others. The bridge writes it (fenced) on first contact in every mode — including--bridge-merge— when it is absent, and--bridge-refreshoverwrites the whole file. An existing unfencedAGENTS.md(another tool's) is safely skipped under--bridge-merge. Always prefer--bridge-mergefor Goose and reviewreferences/bridge-refresh-safety.md(in the repo) before any--bridge-refresh.
Fence Convention¶
Target entry files emitted by the bridge contain AGENTTEAMS-BRIDGE fences (distinct from the AGENTTEAMS fences used by the agent-template emit pipeline):
<!-- AGENTTEAMS-BRIDGE:BEGIN <region-id> v=<version> -->
<bridge-managed content>
<!-- AGENTTEAMS-BRIDGE:END <region-id> -->
--bridge-merge updates only the content inside these fences. Place consumer-side notes, project-specific context, or richer documentation OUTSIDE the fences so they survive every merge.