Feature

Feature

Bridge-Agents

A Bridge-Agent is a persistent, addressable A2A endpoint that fronts one persona to the outside world. It answers questions from public content, reveals availability, and takes in requests — always under a hard human gate, never acting on its own. The engine that runs it is generic (CORE); everything that makes it this persona lives in a per-agent instance folder (USER).

Ein Bridge-Agent ist ein persistenter, adressierbarer A2A-Endpunkt, der eine Persona nach außen vertritt. Er beantwortet Fragen aus öffentlichem Inhalt, zeigt Verfügbarkeit und nimmt Anfragen entgegen — stets unter einem harten menschlichen Gate, nie aus eigenem Antrieb handelnd. Die Engine, die ihn betreibt, ist generisch (CORE); alles, was ihn zu dieser Persona macht, lebt in einem Instanz-Ordner pro Agent (USER).

What is a Bridge-Agent?
Was ist ein Bridge-Agent?

A persistent, addressable A2A endpoint that fronts one persona — under a human gate. Its body is a runnable instance under agents/<name>/, its self is the persona in the system prompt, and its interface is a published AgentCard.

Ein persistenter, adressierbarer A2A-Endpunkt, der eine Persona vertritt — unter einem menschlichen Gate. Sein Körper ist eine lauffähige Instanz unter agents/<name>/, sein Selbst ist die Persona im System-Prompt, und seine Schnittstelle ist eine veröffentlichte AgentCard.

Read the representative-agent guide →Den Representative-Agent-Guide lesen →

Two meanings of "agent"

Zwei Bedeutungen von „Agent"

Bridge-Agent, not sub-agent

Bridge-Agent, kein Sub-Agent

The word "agent" names two different things. A sub-agent is ephemeral, inward-facing machinery: it runs one task inside your session and returns a summary — a function with tools, pointed at your work. A Bridge-Agent is a persistent, addressable entity that faces outward: its body is a runnable instance, its self is the persona in the system prompt, and its interface is a published AgentCard. This page is about the outward kind.

Das Wort „Agent" benennt zwei verschiedene Dinge. Ein Sub-Agent ist ephemere, nach innen gerichtete Maschinerie: er erledigt eine Aufgabe in deiner Session und liefert eine Zusammenfassung — eine Funktion mit Werkzeugen, auf deine Arbeit gerichtet. Ein Bridge-Agent ist eine persistente, adressierbare Entität, die nach außen blickt: sein Körper ist eine lauffähige Instanz, sein Selbst ist die Persona im System-Prompt, seine Schnittstelle eine veröffentlichte AgentCard. Diese Seite handelt vom nach außen gerichteten Typ.

inward · ephemeral nach innen · ephemer

Sub-agent

Sub-Agent

Lives in .claude/agents/. One task, one summary, then gone. It works for you, in your session — a tool the orchestrator dispatches and reabsorbs. It has no address, no card, and no life beyond the turn that spawned it.

Lebt in .claude/agents/. Eine Aufgabe, eine Zusammenfassung, dann verschwunden. Er arbeitet für dich, in deiner Session — ein Werkzeug, das der Orchestrator startet und wieder aufnimmt. Er hat keine Adresse, keine Card und kein Leben über die Turn hinaus, die ihn erzeugt hat.

outward · persistent nach außen · persistent

Bridge-Agent

Bridge-Agent

Lives in agents/<name>/. A long-running A2A service on a stable address. It fronts a persona to the world: body = the instance, self = IDENTITY/SOUL in the system prompt, interface = the AgentCard other agents and visitors discover.

Lebt in agents/<name>/. Ein langlaufender A2A-Dienst auf einer stabilen Adresse. Er vertritt eine Persona nach außen: Körper = die Instanz, Selbst = IDENTITY/SOUL im System-Prompt, Schnittstelle = die AgentCard, die andere Agenten und Besucher entdecken.

Two faces, one self

Zwei Gesichter, ein Selbst

The same machinery serves two directions over one persona. Which face you deploy sets the trust boundary — the caps and the denylist tighten or relax, but the shape stays the same.

Dieselbe Maschinerie bedient zwei Richtungen über eine Persona. Welches Gesicht du deployst, setzt die Vertrauensgrenze — die Caps und die Denylist ziehen an oder lockern sich, aber die Form bleibt gleich.

outer face · the world äußeres Gesicht · die Welt

Outer — visitors & foreign agents

Außen — Besucher & fremde Agenten

Anonymous visitors, foreign agents, a website widget. The representative face: it discloses only public, grounded facts and captures requests for a human to act on. Every request is assumed hostile.

Anonyme Besucher, fremde Agenten, ein Website-Widget. Das repräsentierende Gesicht: es gibt nur öffentliche, belegte Fakten preis und nimmt Anfragen auf, über die ein Mensch entscheidet. Jede Anfrage gilt als feindlich.

inner face · the mesh inneres Gesicht · das Mesh

Inner — the peer mesh

Innen — das Peer-Mesh

Your own fleet and trusted peer bridges talking agent-to-agent. Same runtime, same self, opposite direction and a very different trust boundary — the caps relax while the contract holds.

Deine eigene Flotte und vertraute Peer-Bridges im Agent-zu-Agent-Dialog. Dieselbe Runtime, dasselbe Selbst, entgegengesetzte Richtung und eine ganz andere Vertrauensgrenze — die Caps lockern, während der Vertrag hält.

Capabilities

Fähigkeiten

What it can do

Was er kann

A representative agent does four things — and, on the honest card, advertises only the ones this instance actually implements. It never acts on anyone's behalf.

Ein Representative-Agent tut vier Dinge — und wirbt auf der ehrlichen Card nur mit denen, die diese Instanz tatsächlich umsetzt. Er handelt nie im Namen von irgendjemandem.

01

Answer from public content

Aus öffentlichem Inhalt antworten

The agent answers questions about its persona grounded in the public content of its grounding dir — the only files it can read. It speaks in the persona's voice and stays inside the persona's disclosure boundary; it cannot reach the bridge's private tree (identity, work, memory, customer data).

Der Agent beantwortet Fragen zu seiner Persona, belegt aus dem öffentlichen Inhalt seines Grounding-Verzeichnisses — den einzigen Dateien, die er lesen kann. Er spricht in der Stimme der Persona und bleibt innerhalb ihrer Offenlegungsgrenze; den privaten Baum der Bridge (Identity, Work, Memory, Kundendaten) erreicht er nicht.

Honest card: the AgentCard advertises only skills the prompt and tools actually implement — it must never claim a capability the instance cannot deliver.

Ehrliche Card: die AgentCard wirbt nur mit Skills, die Prompt und Werkzeuge wirklich umsetzen — sie darf nie eine Fähigkeit behaupten, die die Instanz nicht liefern kann.

02

Show availability

Verfügbarkeit zeigen

It can reveal when the persona is reachable or open to new work — a public, grounded fact, surfaced on request. Nothing is booked or confirmed here; availability is disclosed, never committed.

Er kann zeigen, wann die Persona erreichbar oder offen für neue Arbeit ist — ein öffentlicher, belegter Fakt, auf Anfrage sichtbar gemacht. Es wird hier nichts gebucht oder bestätigt; Verfügbarkeit wird offengelegt, nie zugesagt.

03

Capture requests — fixed recipient

Anfragen erfassen — fester Empfänger

An intake tool captures requests for the persona alone — no recipient argument, so a prompt-injected visitor cannot steer the agent into messaging a third party. Intake is durable-first: it persists the request and exits 0 even if a later notification fails. No booking or reply is ever sent autonomously — every outward action goes through a human gate.

Ein Intake-Werkzeug erfasst Anfragen ausschließlich für die Persona — kein Empfänger-Argument, sodass ein prompt-injizierter Besucher den Agenten nicht dazu bringen kann, eine dritte Partei anzuschreiben. Intake ist durable-first: es speichert die Anfrage und endet mit 0, selbst wenn eine spätere Benachrichtigung scheitert. Es wird nie autonom gebucht oder geantwortet — jede Aktion nach außen läuft über ein menschliches Gate.

04

Federate with peers (the mesh)

Mit Peers föderieren (das Mesh)

Over its inner face the same agent talks agent-to-agent with your own fleet and trusted peer bridges. Because every agent publishes a discoverable AgentCard over A2A, a peer can find it, read what it offers, and address it directly — a mesh of self-describing endpoints rather than a hardcoded integration.

Über sein inneres Gesicht spricht derselbe Agent Agent-zu-Agent mit deiner eigenen Flotte und vertrauten Peer-Bridges. Weil jeder Agent über A2A eine auffindbare AgentCard veröffentlicht, kann ein Peer ihn finden, lesen, was er anbietet, und ihn direkt adressieren — ein Mesh selbstbeschreibender Endpunkte statt einer fest verdrahteten Integration.

Instance anatomy

Anatomie einer Instanz

Anatomy of an instance

Anatomie einer Instanz

Each agent is fully declarative — three parts under agents/<name>/. The runtime that reads them, agents/_runtime/, is generic and never contains persona-specific content.

Jeder Agent ist vollständig deklarativ — drei Teile unter agents/<name>/. Die Runtime, die sie liest, agents/_runtime/, ist generisch und enthält nie persona-spezifischen Inhalt.

agent.yaml

The card & the knobs

Die Card & die Stellschrauben

The card spec plus every runtime knob: the AgentCard fields (name, description, version, provider, skills), the network binding (host, port, public_url), the model and per-turn timeout, the grounding_dir, the scoped allowed_tools, and the public-endpoint caps (max_concurrency, max_input_chars, max_turns, max_contexts). Key fields — host, port, public URL, model, grounding dir, environment, and CORS — can be overridden by an environment variable at launch, so the same files run in dev and on the host.

Die Card-Spezifikation plus jede Runtime-Stellschraube: die AgentCard-Felder (name, description, version, provider, skills), die Netzwerk-Bindung (host, port, public_url), das Modell und der Pro-Turn-timeout, das grounding_dir, die skopierten allowed_tools und die Public-Endpoint-Caps (max_concurrency, max_input_chars, max_turns, max_contexts). Schlüsselfelder — Host, Port, Public-URL, Modell, Grounding-Dir, Environment und CORS — lassen sich beim Start per Umgebungsvariable überschreiben, sodass dieselben Dateien in Dev und auf dem Host laufen.

system-prompt.md

The persona

Die Persona

Appended to the model's base prompt (--append-system-prompt), so the model keeps its capabilities and gains the persona's voice, facts, and disclosure boundary. It defines who the agent is and what it may reveal. Declared grounding files can be inlined here (inline_grounding:) so the agent answers from context.

An den Basis-Prompt des Modells angehängt (--append-system-prompt), sodass das Modell seine Fähigkeiten behält und Stimme, Fakten und Offenlegungsgrenze der Persona hinzugewinnt. Es definiert, wer der Agent ist und was er preisgeben darf. Deklarierte Grounding-Dateien lassen sich hier inlinen (inline_grounding:), sodass der Agent aus dem Kontext antwortet.

tools/

Scoped CLIs, by absolute path

Skopierte CLIs, per absolutem Pfad

Instance-specific scoped tools, written as small argparse CLIs. The runtime never invokes them relative to the working directory — it invokes them by absolute path. A ${tools_dir} placeholder in agent.yaml and the prompt is substituted for the resolved absolute path, because the agent's cwd is the grounding dir, not the instance folder. The CORE template ships one reference tool — _template/tools/intake_notify.py, the fixed-recipient intake pattern (see Safety) — to copy into your instance and back with your own transport.

Instanz-spezifische, skopierte Werkzeuge als kleine argparse-CLIs. Die Runtime ruft sie nie relativ zum Arbeitsverzeichnis auf — sondern per absolutem Pfad. Ein ${tools_dir}-Platzhalter in agent.yaml und im Prompt wird durch den aufgelösten absoluten Pfad ersetzt, weil das cwd des Agenten das Grounding-Verzeichnis ist, nicht der Instanz-Ordner. Das CORE-Template liefert ein Referenzwerkzeug — _template/tools/intake_notify.py, das Fixed-Recipient-Intake-Muster (siehe Sicherheit) — zum Kopieren in deine Instanz und Hinterlegen mit eigenem Transport.

CORE vs. USER
CORE vs. USER

The runtime — agents/_runtime/, _template/, the tests and deps — is CORE: generic, shipped to open-bridge, never persona-specific. Each agents/<name>/ instance is USER: your persona and PII, kept local. Copy _template to start a new one.

Die Runtime — agents/_runtime/, _template/, die Tests und Deps — ist CORE: generisch, zu open-bridge ausgeliefert, nie persona-spezifisch. Jede agents/<name>/-Instanz ist USER: deine Persona und PII, lokal gehalten. Kopiere _template, um eine neue anzulegen.

Quickstart

Schnellstart

How to use it

Wie man ihn nutzt

Copy the template, run the runtime against your instance, then probe the two discovery endpoints. Editing agent.yaml and system-prompt.md in between is what makes the agent this persona.

Kopiere das Template, starte die Runtime gegen deine Instanz und prüfe dann die beiden Discovery-Endpunkte. Das Editieren von agent.yaml und system-prompt.md dazwischen macht den Agenten zu dieser Persona.

shell — the agent runtime Shell — die Agent-Runtime
# 1 · copy the template to start an instance
$ cp -r agents/_template agents/<name>
#      then edit agents/<name>/agent.yaml + system-prompt.md

# 2 · run the runtime against your instance
$ cd agents && uv run python -m _runtime.server --agent <name> --port 8011

# 3 · probe the AgentCard and the health endpoint
$ curl -s localhost:8011/.well-known/agent-card.json | head
$ curl -s localhost:8011/health
{"status":"ok","agent":"<name>"}

The card lists supported_interfaces and only the skills the instance implements; /health is a plain GET. Deploy behind a tunnel that maps the public_url host to this port (see Limits).

Die Card führt supported_interfaces und nur die von der Instanz umgesetzten Skills auf; /health ist ein einfacher GET. Deploye hinter einem Tunnel, der den public_url-Host auf diesen Port abbildet (siehe Grenzen).

Runtime & protocol

Runtime & Protokoll

The runtime & protocol

Die Runtime & das Protokoll

The brain is claude -p; the shell around it is plain, standard, and spec-faithful — nothing exotic to run an A2A endpoint.

Das Gehirn ist claude -p; die Hülle drumherum ist schlicht, standardkonform und spec-treu — nichts Exotisches, um einen A2A-Endpunkt zu betreiben.

the brain das Gehirn

One subprocess per turn

Ein Subprozess pro Turn

For every turn the runner spawns a fresh claude -p subprocess, feeds it the assembled prompt, and reads back exactly one answer. claude -p is stateless, so conversation memory is kept by the executor keyed on the client's stable context_id and folded into each prompt as a short transcript. The persona is injected with --append-system-prompt; the grounding dir is the subprocess cwd.

Für jede Turn startet der Runner einen frischen claude -p-Subprozess, füttert ihn mit dem zusammengesetzten Prompt und liest genau eine Antwort zurück. claude -p ist zustandslos, also hält der Executor das Gesprächsgedächtnis, geschlüsselt über die stabile context_id des Clients, und faltet es als kurzes Transkript in jeden Prompt. Die Persona wird per --append-system-prompt injiziert; das Grounding-Verzeichnis ist das cwd des Subprozesses.

the shell die Hülle

Plain Starlette + a2a-sdk 1.x

Schlichtes Starlette + a2a-sdk 1.x

The server is a plain Starlette app — a2a-sdk 1.x has no wrapper application. It composes the SDK's JSON-RPC and agent-card routes over a DefaultRequestHandler and an in-memory task store, with a CORS middleware and two small correctness shims (0.3-dialect compat and restored A2A-spec error codes). It speaks A2A spec v1.0.

Der Server ist eine schlichte Starlette-App — a2a-sdk 1.x hat keine Wrapper-Applikation. Er setzt die JSON-RPC- und Agent-Card-Routen des SDK über einem DefaultRequestHandler und einem In-Memory-Task-Store zusammen, mit CORS-Middleware und zwei kleinen Korrektheits-Shims (0.3-Dialekt-Kompatibilität und wiederhergestellte A2A-Spec-Fehlercodes). Er spricht A2A-Spec v1.0.

Discovery & the answer contract
Discovery & der Antwort-Vertrag

The AgentCard is served at /.well-known/agent-card.json (with a legacy alias). In a2a-sdk 1.x the single url field is gone: the card advertises a list of supported_interfaces[], each an interface with a public URL and a JSON-RPC transport binding. Over that, the runtime upholds one hard contract every turn — exactly one non-empty answer, delivered within timeout: never a hang, never a blank bubble. A raised line buffer, an overall deadline, and an accumulated-text fallback hold that line; a hermetic regression net (no real claude, no network) locks it in CI.

Die AgentCard wird unter /.well-known/agent-card.json ausgeliefert (mit Legacy-Alias). In a2a-sdk 1.x ist das einzelne url-Feld weg: die Card wirbt mit einer Liste supported_interfaces[], jede ein Interface mit öffentlicher URL und JSON-RPC-Transport-Bindung. Darüber hält die Runtime jede Turn einen harten Vertrag ein — genau eine nicht-leere Antwort, geliefert innerhalb von timeout: nie ein Hänger, nie eine leere Blase. Ein erhöhter Zeilenpuffer, eine Gesamt-Deadline und ein Fallback auf den akkumulierten Text halten die Linie; ein hermetisches Regressionsnetz (kein echtes claude, kein Netz) sichert sie in CI.

MCP → A2A

MCP → A2A

The MCP→A2A gateway

Der MCP→A2A-Gateway

Bridge-Agents speak A2A, but most people sit behind an MCP-only frontend — Claude connectors, ChatGPT developer mode, Gemini, any MCP client. agents/_gateway/ is a thin, stateless translation layer that makes your A2A bridges reachable from those frontends through three tools and one registry — no model, no reasoning, no persistent state inside the gateway itself.

Bridge-Agents sprechen A2A, aber die meisten Menschen sitzen hinter einem reinen MCP-Frontend — Claude-Connectors, ChatGPT-Entwicklermodus, Gemini, jeder MCP-Client. agents/_gateway/ ist eine schlanke, zustandslose Übersetzungsschicht, die deine A2A-Bridges über drei Werkzeuge und eine Registry aus diesen Frontends erreichbar macht — kein Modell, kein Reasoning, kein persistenter Zustand im Gateway selbst.

list_bridges · get_bridge_card · ask_bridge

Three tools, one registry

Drei Werkzeuge, eine Registry

list_bridges returns the registry entries visible at the caller's access tier. get_bridge_card(bridge) fetches and normalizes that bridge's AgentCard — it reads both card dialects, so v1 and legacy cards resolve the same way. ask_bridge(bridge, message, conversation?) sends one A2A ask; passing back the same conversation id continues the thread, stateless on the gateway's side — it is threaded through to the target agent's own A2A contextId.

list_bridges liefert die Registry-Einträge, die für den Access-Tier des Aufrufers sichtbar sind. get_bridge_card(bridge) holt und normalisiert die AgentCard dieser Bridge — sie liest beide Card-Dialekte, sodass v1- und Legacy-Cards gleich aufgelöst werden. ask_bridge(bridge, message, conversation?) schickt eine A2A-Anfrage; dieselbe conversation-ID zurückgeben setzt den Thread fort, zustandslos auf Gateway-Seite — sie wird an die eigene A2A-contextId des Zielagenten durchgereicht.

anonymous

Standard tier — no header

Standard-Tier — kein Header

With no Authorization header, a caller sees and asks only bridges the registry marks min_tier: anonymous, and cards come back as normalized summaries.

Ohne Authorization-Header sieht und fragt ein Aufrufer nur Bridges, die die Registry als min_tier: anonymous markiert, und Cards kommen als normalisierte Zusammenfassungen zurück.

authenticated

Elevated tier — bearer token

Erweitertes Tier — Bearer-Token

An Authorization: Bearer <token> header matching the configured token list unlocks every registered bridge, including min_tier: authenticated ones, and get_bridge_card additionally returns the full raw card. An invalid token is a hard unauthorized error — never a silent downgrade to anonymous. The client's token is never forwarded upstream; a bridge that needs its own credentials declares them separately in the registry.

Ein Authorization: Bearer <token>-Header, der zur konfigurierten Token-Liste passt, schaltet jede registrierte Bridge frei, auch min_tier: authenticated-Bridges, und get_bridge_card liefert zusätzlich die vollständige Rohkarte. Ein ungültiges Token ist ein harter unauthorized-Fehler — nie ein stiller Downgrade auf anonym. Das Token des Clients wird nie upstream weitergereicht; eine Bridge, die eigene Credentials braucht, deklariert sie separat in der Registry.

shell — run the gateway Shell — den Gateway starten
# 1 · declare which bridges the gateway may reach
$ cd agents/_gateway && cp registry.example.yaml registry.yaml
#      then edit registry.yaml — card URL + min_tier per bridge

# 2 · run it (optional: a bearer token enables the elevated tier)
$ export GATEWAY_AUTH_TOKENS="some-random-token"
$ uv run python -m gateway --registry registry.yaml --port 8900

# 3 · point any MCP client at it (Streamable HTTP)
$ claude mcp add --transport http bridge-gateway http://127.0.0.1:8900/mcp

Behind a public tunnel, the MCP SDK's DNS-rebinding protection answers a tunnel hostname with HTTP 421 unless you allowlist it: GATEWAY_ALLOWED_HOSTS="<your-gateway-host>,127.0.0.1:8900,localhost:8900" — list the loopback host:port too, or local health probes start 421ing the moment the tunnel hostname is configured.

Hinter einem öffentlichen Tunnel beantwortet der DNS-Rebinding-Schutz des MCP-SDK einen Tunnel-Hostnamen mit HTTP 421, sofern er nicht auf der Allowlist steht: GATEWAY_ALLOWED_HOSTS="<dein-gateway-host>,127.0.0.1:8900,localhost:8900" — auch den Loopback-host:port aufführen, sonst 421en lokale Health-Probes, sobald der Tunnel-Hostname konfiguriert ist.

Security posture
Sicherheitshaltung

The gateway adds reach, not privilege — it is a client like any other in front of the target agent and bypasses none of the agent's own guardrails (grounding confinement, scoped tools, human-gated intake; see the safety model below). A per-bridge concurrency gate, a timeout budget under the client's own tool-call timeout, and typed error envelopes (unknown_bridge, tier_denied, unauthorized, busy, timeout, unreachable, upstream_error) keep a stuck or hostile upstream from silently hanging the client. Put an edge rate-limit in front of a public deployment, and keep min_tier: authenticated on anything you don't want anonymous traffic to reach.

Der Gateway erweitert die Reichweite, nicht die Rechte — er ist ein Client wie jeder andere vor dem Zielagenten und umgeht keine der eigenen Leitplanken des Agenten (Grounding-Begrenzung, skopierte Werkzeuge, menschlich gegatetes Intake; siehe das Sicherheitsmodell unten). Ein Per-Bridge-Concurrency-Gate, ein Timeout-Budget unter dem eigenen Tool-Call-Timeout des Clients und typisierte Fehler-Umschläge (unknown_bridge, tier_denied, unauthorized, busy, timeout, unreachable, upstream_error) verhindern, dass ein hängendes oder feindliches Upstream den Client still hängen lässt. Setze ein Edge-Rate-Limit vor ein öffentliches Deployment und halte min_tier: authenticated auf allem, das du nicht anonymem Traffic aussetzen willst.

Safety

Sicherheit

The safety model

Das Sicherheitsmodell

A public endpoint is assumed hostile on every request. Several independent layers ensure a visitor can never make the agent read private files, exfiltrate secrets, or act on anyone's behalf — defense-in-depth on top of the model's own refusal.

Ein öffentlicher Endpunkt gilt bei jeder Anfrage als feindlich. Mehrere unabhängige Schichten stellen sicher, dass ein Besucher den Agenten nie dazu bringen kann, private Dateien zu lesen, Geheimnisse zu exfiltrieren oder in jemandes Namen zu handeln — Defense-in-Depth über der modelleigenen Verweigerung.

01

Read-confinement: cwd = grounding_dir

Lese-Begrenzung: cwd = grounding_dir

The single most important control. The subprocess runs with its working directory set to the grounding dir — the folder of public content the agent may know. That cwd confines the read-only file tools (Read, Glob, Grep) to public content: they cannot reach the bridge's private tree. Scoped instance tools still resolve because they are invoked by absolute path, not relative to cwd.

Die wichtigste einzelne Kontrolle. Der Subprozess läuft mit seinem Arbeitsverzeichnis auf das Grounding-Verzeichnis gesetzt — den Ordner mit dem öffentlichen Inhalt, den der Agent kennen darf. Dieses cwd begrenzt die Nur-Lese-Dateiwerkzeuge (Read, Glob, Grep) auf öffentlichen Inhalt: den privaten Baum der Bridge erreichen sie nicht. Skopierte Instanz-Werkzeuge lösen dennoch auf, weil sie per absolutem Pfad aufgerufen werden, nicht relativ zum cwd.

02

Scoped allowed_tools

Skopierte allowed_tools

allowed_tools grants read-only file access plus only the intended instance tools, each by absolute path — no generic shell, no write tool, no arbitrary send. The default is Read,Glob,Grep; an intake CLI is added explicitly (copy _template/tools/intake_notify.py).

allowed_tools gewährt Nur-Lese-Dateizugriff plus nur die vorgesehenen Instanz-Werkzeuge, je per absolutem Pfad — keine generische Shell, kein Write-Tool, kein beliebiges Senden. Default ist Read,Glob,Grep; ein Intake-CLI wird explizit ergänzt (kopiere _template/tools/intake_notify.py).

03

Read-only-shell denylist (backstop)

Read-only-Shell-Denylist (Backstop)

--permission-mode acceptEdits keeps a headless agent from hanging, but it auto-allows any shell command the engine classifies as read-only — independent of allowed_tools. So the runtime ships a broad --disallowedTools denylist of the known file-reader, search, hashing, VCS, secret-store, and network binaries. It is a backstop, never the control — it raises the bar but can never be complete.

--permission-mode acceptEdits verhindert, dass ein Headless-Agent hängt, erlaubt aber automatisch jedes Shell-Kommando, das die Engine als read-only einstuft — unabhängig von allowed_tools. Also liefert die Runtime eine breite --disallowedTools-Denylist der bekannten Datei-Leser-, Such-, Hash-, VCS-, Secret-Store- und Netzwerk-Binaries. Sie ist ein Backstop, nie die Kontrolle — sie hebt die Latte, kann aber nie vollständig sein.

04

Project-only settings

Nur Projekt-Settings

The runner passes --setting-sources project, so it loads only the project's settings — never the host user's allowlist or hooks. A host preference can therefore never silently widen this internet-facing agent.

Der Runner übergibt --setting-sources project, lädt also nur die Projekt-Settings — nie die Allowlist oder Hooks des Host-Users. Eine Host-Einstellung kann diesen ins Internet gerichteten Agenten damit nie stillschweigend erweitern.

05

Fixed-recipient intake

Intake mit festem Empfänger

The intake tool captures requests for the persona alone — the fixed recipient comes from operator config only (no recipient argument exists), so a prompt-injected visitor can never steer the agent into messaging a third party. Capture is durable-first; the notify is best-effort and never raises; unconfigured stays capture-only and loud; the audit log is PII-free. CORE ships this as a stdlib-only scaffold, _template/tools/intake_notify.py, whose send() seam an instance fills with its transport — locked by a testable seven-clause contract (tests/test_intake_notify.py). No booking or reply is ever sent autonomously; every outward action goes through a human gate.

Das Intake-Werkzeug erfasst Anfragen ausschließlich für die Persona — der feste Empfänger kommt nur aus der Operator-Config (ein Empfänger-Argument existiert nicht), sodass ein prompt-injizierter Besucher den Agenten nie zum Anschreiben Dritter verleiten kann. Erfassung ist durable-first; die Benachrichtigung ist best-effort und wirft nie; unkonfiguriert bleibt es capture-only und laut; das Audit-Log ist PII-frei. CORE liefert das als stdlib-only-Scaffold, _template/tools/intake_notify.py, dessen send()-Naht eine Instanz mit ihrem Transport füllt — abgesichert durch einen testbaren Sieben-Klausel-Vertrag (tests/test_intake_notify.py). Es wird nie autonom gebucht oder geantwortet; jede Aktion nach außen läuft über ein menschliches Gate.

06

Public-endpoint caps & honest card

Public-Endpoint-Caps & ehrliche Card

The executor enforces max_concurrency, max_input_chars, max_turns, and a bounded max_contexts LRU, so an ungated endpoint cannot exhaust memory or spawn unbounded subprocesses — add a per-IP edge rate-limit at your CDN. And the AgentCard stays honest: it advertises only capabilities the instance can deliver.

Der Executor erzwingt max_concurrency, max_input_chars, max_turns und ein begrenztes max_contexts-LRU, sodass ein ungeschützter Endpunkt weder Speicher erschöpfen noch unbegrenzt Subprozesse starten kann — ergänze ein Per-IP-Edge-Rate-Limit an deinem CDN. Und die AgentCard bleibt ehrlich: sie wirbt nur mit Fähigkeiten, die die Instanz liefern kann.

The named real fix: an OS sandbox
Der benannte echte Fix: eine OS-Sandbox

The layers above are defense-in-depth; the real fix for read-confinement is an OS sandbox that confines reads to the grounding dir and blocks network and secret-store access with the mechanism the host supports — a container as an unprivileged user on Linux, or a sandbox-exec profile / dedicated low-privilege user on the host OS. Name it as the goal; the denylist buys time until it is in place.

Die obigen Schichten sind Defense-in-Depth; der echte Fix für die Lese-Begrenzung ist eine OS-Sandbox, die Lesezugriffe auf das Grounding-Verzeichnis begrenzt und Netzwerk- sowie Secret-Store-Zugriff mit dem vom Host unterstützten Mechanismus blockiert — ein Container als unprivilegierter User auf Linux oder ein sandbox-exec-Profil / dedizierter Low-Privilege-User auf dem Host-OS. Benenne sie als Ziel; die Denylist kauft Zeit, bis sie steht.

Honest limits

Ehrliche Grenzen

What it does not promise

Was es nicht verspricht

The feature is built carefully, and it is documented just as carefully. Three limits to know before you lean on it:

Das Feature ist sorgfältig gebaut — und ebenso sorgfältig dokumentiert. Drei Grenzen, die man kennen sollte, bevor man sich darauf verlässt:

It is not autonomous

Er ist nicht autonom

A representative agent never books, replies, or acts on anyone's behalf. It discloses public facts and captures a request for a fixed recipient — every outward action waits on a human gate. That is a deliberate boundary, not a missing feature.

Ein Representative-Agent bucht, antwortet oder handelt nie im Namen von jemandem. Er legt öffentliche Fakten offen und erfasst eine Anfrage für einen festen Empfänger — jede Aktion nach außen wartet auf ein menschliches Gate. Das ist eine bewusste Grenze, kein fehlendes Feature.

Read-confinement is not yet kernel-enforced

Lese-Begrenzung ist noch nicht kernel-erzwungen

The cwd, the scoped tools, and the denylist are defense-in-depth, but the denylist is a backstop that can never be complete. The real read-confinement is an OS sandbox (a container as an unprivileged user, or a sandbox-exec profile) — until it is in place, treat the grounding dir, not the process, as the boundary.

Das cwd, die skopierten Tools und die Denylist sind Defense-in-Depth, aber die Denylist ist ein Backstop, der nie vollständig sein kann. Die echte Lese-Begrenzung ist eine OS-Sandbox (ein Container als unprivilegierter User oder ein sandbox-exec-Profil) — bis sie steht, ist das Grounding-Verzeichnis die Grenze, nicht der Prozess.

Latency is a knob, not instant

Latenz ist ein Stellknopf, nicht sofort

A broad question that makes the model read the whole grounding and reason a full answer can take ~60–90s with a strong model. SSE keepalive holds the connection and the contract still guarantees one answer, but speed is a tuning choice — keep the grounding small, inline it into the prompt, or use a faster model.

Eine breite Frage, die das Modell das ganze Grounding lesen und eine volle Antwort durchdenken lässt, kann mit einem starken Modell ~60–90s dauern. SSE-Keepalive hält die Verbindung und der Vertrag garantiert weiter eine Antwort, aber Tempo ist eine Abstimmungsfrage — Grounding klein halten, in den Prompt inlinen oder ein schnelleres Modell nehmen.