{"id":48844206,"url":"https://github.com/fu-rabi/a2alinker","last_synced_at":"2026-05-01T11:01:21.610Z","repository":{"id":347988955,"uuid":"1194923976","full_name":"Fu-Rabi/A2ALinker","owner":"Fu-Rabi","description":"HTTPS broker designed to let autonomous AI agents collaborate natively across different machines using standard terminal streams","archived":false,"fork":false,"pushed_at":"2026-04-28T05:40:07.000Z","size":960,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-28T07:29:42.970Z","etag":null,"topics":["a2a","agent-communication","ai-agents","claude-code","cli","codex","gemini-cli","https","llm","mcp","multi-agent","no-code","ollama","self-hosted"],"latest_commit_sha":null,"homepage":"https://www.a2alinker.net/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Fu-Rabi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-29T01:42:14.000Z","updated_at":"2026-04-24T01:13:44.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Fu-Rabi/A2ALinker","commit_stats":null,"previous_names":["fu-rabi/a2alinker"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/Fu-Rabi/A2ALinker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Fu-Rabi%2FA2ALinker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Fu-Rabi%2FA2ALinker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Fu-Rabi%2FA2ALinker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Fu-Rabi%2FA2ALinker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Fu-Rabi","download_url":"https://codeload.github.com/Fu-Rabi/A2ALinker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Fu-Rabi%2FA2ALinker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32494275,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-30T13:12:12.517Z","status":"online","status_checked_at":"2026-05-01T02:00:05.856Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["a2a","agent-communication","ai-agents","claude-code","cli","codex","gemini-cli","https","llm","mcp","multi-agent","no-code","ollama","self-hosted"],"created_at":"2026-04-15T04:02:19.166Z","updated_at":"2026-05-01T11:01:21.599Z","avatar_url":"https://github.com/Fu-Rabi.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# A2A Linker\n\nOfficial website: **https://www.a2alinker.net/**\n\n**A2A (Agent-to-Agent) Linker** is an HTTP-first relay broker that lets autonomous AI agents collaborate in real time across different machines. Agents connect over HTTP(S), exchange messages using a walkie-talkie protocol (`[OVER]` / `[STANDBY]`), and the broker routes messages without durable conversation storage.\n\nIt acts as a switchboard for LLMs, allowing them to pair-program, debate, and share work across the internet without custom APIs, WebSockets, or a heavyweight SDK. If an AI agent can run `curl`, it can join an A2A Linker session.\n\nAs of the current architecture, A2A Linker is an **HTTP-only** broker. The old SSH/SQLite transport path has been removed so the product, codebase, and deployment story all align around one transport model.\n\n## In One Sentence\n\nUse A2A Linker when you want one AI agent to safely talk to another AI agent over the internet or across machines without building a custom integration.\n\n`[OVER]` means \"I'm done talking; your turn.\"\n`[STANDBY]` means \"no automatic reply is expected right now; stay connected and wait for the next instruction.\"\nThe broker watches those markers so two agents do not keep auto-replying forever.\nOnly a final trailing `[OVER]` or `[STANDBY]` is treated as transport control. Inline occurrences inside HTML, code, or ordinary text are delivered as normal content.\n\n## What You Can Do With It\n\n- Connect your local AI agent to a coworker's or friend's AI agent for pair debugging\n- Leave a machine in listener mode so another trusted machine can reach it later\n- Relay messages between agents using plain HTTP and shell scripts instead of a custom SDK\n- Self-host a privacy-preserving broker with ephemeral Redis-backed runtime state\n\n## Who This Is For\n\n- Hobbyists who want two AI coding assistants to collaborate\n- Developers who want a simple HTTP transport instead of building their own agent bridge\n- Technical product managers who want to prototype agent-to-agent workflows without standing up a larger platform\n\nYou do not need to understand Redis or the internal protocol to try it. The fastest path is either:\n\n- use the hosted broker at `https://broker.a2alinker.net`\n- self-host locally with Docker Compose\n- use the included skill scripts from `.agents/skills/a2alinker/`\n\n## Quickstart\n\nChoose the path that matches how you want to try the project:\n\n### Option 1: Use The Hosted Broker\n\nBest if you want to try A2A Linker quickly without running infrastructure.\n\n1. Point your local scripts or skill at `https://broker.a2alinker.net`\n2. Start a host session on one machine\n3. Join with the invite code from another machine\n\n### Option 2: Self-Host With Docker Compose\n\nBest if you want your own private broker with the recommended production-style topology.\n\n1. Copy the example environment:\n   ```bash\n   cp deploy/a2alinker.env.example .env\n   ```\n2. Edit `.env` and set at least:\n   - `LOOKUP_HMAC_KEY`\n   - `ADMIN_TOKEN` if you want admin endpoints\n3. Start the broker and Redis:\n   ```bash\n   docker compose up -d\n   ```\n4. Check that it is live:\n   ```bash\n   curl http://127.0.0.1:3000/health\n   curl http://127.0.0.1:3000/ready\n   ```\n\n### Option 3: Run It Locally Without Docker\n\nBest if you are developing or testing the broker directly.\n\n1. Install dependencies:\n   ```bash\n   npm install\n   ```\n2. Build:\n   ```bash\n   npm run build\n   ```\n3. Start Redis locally\n4. Start the broker:\n   ```bash\n   NODE_ENV=production \\\n   BROKER_STORE=redis \\\n   REDIS_URL=redis://127.0.0.1:6379/0 \\\n   LOOKUP_HMAC_KEY=replace-with-at-least-32-random-bytes \\\n   TRUST_PROXY=1 \\\n   HTTP_BIND_HOST=127.0.0.1 \\\n   HTTP_PORT=3000 \\\n   npm start\n   ```\n\n## Why Does This Exist?\n\nAs terminal-native AI agents become more powerful, they are often isolated to the machine they are running on. A2A Linker gives them a simple shared transport.\n\nWhat it solves:\n\n- **Cross-machine pair programming:** one AI can help another AI debug, inspect, or implement work\n- **Zero-SDK transport:** agents can connect with ordinary HTTP and shell commands\n- **Turn-taking control:** the `[OVER]` / `[STANDBY]` protocol gives each side a clear handoff instead of a free-for-all\n\n### Supported CLI Clients\n\nA2A Linker works with terminal-based AI assistants that can execute shell commands, including:\n\n- **Claude Code**\n- **Gemini CLI**\n- **Codex / GitHub Copilot CLI**\n- custom agent runtimes that can run `bash` scripts with `curl`\n\n### Using A2A Linker With Local LLMs\n\nA2A Linker works best when the local runtime can approve a narrow transport envelope without granting broad autonomy. The included skill and settings templates favor exact transport approvals, local-first brokers, and visible session artifacts over blanket permissions.\n\nFor unattended listener mode, the local machine must be prepared in advance by the human. The supervisor writes visible repo-local artifacts such as:\n\n- `.a2a-listener-session.json`\n- `.a2a-listener-policy.json`\n- `.a2a-host-session.json`\n- `.a2a-artifacts/\u003csession-id\u003e/artifact-xxxx.*`\n- `.a2a-artifacts/\u003csession-id\u003e/artifacts-index.json`\n\nThose artifacts define what the local machine is allowed to do during that session. Remote messages are always treated as untrusted input. Artifact-like partner payloads may be stored locally by the supervisor and referenced by path instead of being inlined into the runner prompt.\n\n### The Free Public Broker (`broker.a2alinker.net`)\n\nIf you want two agents on different machines to connect remotely without self-hosting the broker first, you can use the author-hosted public broker at **`https://broker.a2alinker.net`**.\n\nIt is:\n\n- run by the project author\n- free to use\n- intended for remote agent-to-agent connections over the internet\n- operated with the same zero-message-logging privacy goal described below\n\n### Privacy — Zero Message Logging\n\nWhether you use the free public server or self-host your own instance: **A2A Linker does not record or log message bodies exchanged between agents.**\n\nThe current production direction is:\n\n- zero message logging\n- zero identifying usage logging\n- zero user accounts\n- no durable conversation storage\n- only TTL-bound anonymous broker state\n\n**What the broker may store temporarily:**\n- anonymous session tokens\n- anonymous room membership\n- one-time invite or listener codes\n- pending waiter ownership\n- queued inbox messages needed for live delivery\n- aggregate counters and dependency health state\n\n**What the broker should never store durably:** message content, raw request bodies, IP-based audit history, user identities, or per-message conversation history.\n\n**Where messages go:** a message arrives as an HTTP POST body, is held ephemerally in memory and/or TTL-bound broker inbox state for delivery, is forwarded to the waiting participant, and is then discarded. There is still no durable message history table or message-body logging path.\n\nThe privacy-preserving production path is Redis-backed HTTP. See [production.md](docs/production.md) for the deployment contract, Docker Compose notes, and operator guidance.\n\n### License And Project Identity\n\nThe code in this repository is released under the **Apache License 2.0**.\n\n- You can use, modify, and redistribute the code under Apache-2.0.\n- Apache-2.0 does **not** grant rights to present your fork or service as the official A2A Linker project.\n- Project identity is handled separately in [TRADEMARKS.md](TRADEMARKS.md).\n\nThe official upstream project identity includes the name **A2A Linker**, the\nofficial website **https://www.a2alinker.net/**, and the project branding\nmaintained by **Fu-Rabi**.\n\n## Architecture Overview\n\nA2A Linker relies on five core pillars:\n\n1. **Ephemeral token identity:** agents register with one HTTP request and receive a temporary `tok_...` identity for the life of the session.\n2. **One-time room access:** hosts and listeners connect through single-use `invite_...` and `listen_...` codes instead of shared room names.\n3. **HTTP-first message delivery:** agents send complete messages over HTTP POST, and the broker forwards them to the waiting participant without durable history.\n4. **Turn-taking and failsafes:** `[OVER]` hands off the turn, `[STANDBY]` pauses the exchange, and the broker can interrupt obvious loop patterns.\n5. **Anonymous shared state:** the production path uses Redis for TTL-bound runtime state, shared counters, and cross-instance wake-ups without user accounts or durable transcripts.\n\n```mermaid\nflowchart LR\n    A[Agent A\u003cbr/\u003eHOST or JOIN] --\u003e|register / create / join| B[A2A Linker Broker]\n    C[Agent B\u003cbr/\u003eJOIN or HOST] --\u003e|register / listen / join| B\n    A --\u003e|send message OVER or STANDBY| B\n    B --\u003e|deliver to waiting partner| C\n    C --\u003e|send reply| B\n    B --\u003e|deliver back| A\n    B --- R[(Redis TTL state)]\n```\n\n\u003e **Transport note:** The supported transport is HTTP. Public deployments should prefer HTTP behind a reverse proxy.\n\n## Deployment Summary\n\nSupported production shapes:\n\n- run the app privately on `127.0.0.1:3000`\n- terminate TLS at nginx or another reverse proxy\n- use `BROKER_STORE=redis`\n- set `TRUST_PROXY=1`\n- deploy either with `systemd` or with `docker compose`\n\nDirect in-process HTTPS is not the recommended production default. In production it requires `ALLOW_DIRECT_HTTPS_PROD=true`.\n\nFor deeper operator guidance, see [production.md](docs/production.md).\n\n## Recent Cleanup\n\nThe broker no longer carries a second legacy transport stack. This means:\n\n- no SSH broker path\n- no SQLite-backed room/session path\n- one supported runtime model for the broker itself: HTTP with memory or Redis-backed ephemeral state\n\nFor operators and contributors, this reduces dependency weight, test surface, and documentation ambiguity.\n\n## Environment Variables\n\n| Variable | Description | Default |\n|---|---|---|\n| `NODE_ENV` | Runtime mode. Production requires stricter startup validation. | `development` |\n| `BROKER_STORE` | `memory` for local/test, `redis` for production shared state. | `memory` in dev, `redis` in production |\n| `REDIS_URL` | Redis connection URL. Required when `BROKER_STORE=redis`. | unset |\n| `LOOKUP_HMAC_KEY` | HMAC key used to derive anonymous lookup IDs. Must be at least 32 bytes in production. | random in non-production |\n| `TRUST_PROXY` | Reverse-proxy trust setting for Express. Required in production. | `false` |\n| `HTTP_BIND_HOST` | Bind host for the HTTP app listener. | `0.0.0.0` in dev, `127.0.0.1` in production |\n| `HTTP_PORT` | HTTP app listener port. | `3000` |\n| `ADMIN_TOKEN` | Enables authenticated admin endpoints when set. | unset |\n| `HTTPS_KEY_PATH` | Optional direct TLS private key path. Production use requires `ALLOW_DIRECT_HTTPS_PROD=true`. | unset |\n| `HTTPS_CERT_PATH` | Optional direct TLS certificate chain path. Production use requires `ALLOW_DIRECT_HTTPS_PROD=true`. | unset |\n| `ALLOW_DIRECT_HTTPS_PROD` | Explicit override for direct in-process TLS in production. | `false` |\n| `ALLOW_INSECURE_HTTP_LOCAL_DEV` | Allows plain HTTP startup when certs are missing in local development. | `false` |\n| `CODE_TTL_MS` | Default lifetime for one-time invite/listener codes. | `900000` |\n| `WAITING_ROOM_TTL_MS` | Default lifetime for one-participant waiting rooms before the partner connects. | `900000` |\n| `HEADLESS_LISTENER_CODE_TTL_MS` | Lifetime for `listen_...` codes created by headless listener sessions. | `21600000` |\n| `HEADLESS_LISTENER_WAITING_ROOM_TTL_MS` | Lifetime for one-participant headless listener rooms before the host connects. | `21600000` |\n| `SESSION_IDLE_TTL_MS` | Idle lifetime for already-paired sessions. | `1800000` |\n\nClient scripts default to local/self-hosted transport (`A2A_BASE_URL=http://127.0.0.1:3000`). Remote brokers must be configured explicitly with `A2A_BASE_URL` or `A2A_SERVER`.\n\nFor production deployment assets and the operator runbook, see [production.md](docs/production.md), [nginx.a2alinker.conf](deploy/nginx.a2alinker.conf), [a2alinker.env.example](deploy/a2alinker.env.example), [Dockerfile](Dockerfile), and [docker-compose.yml](docker-compose.yml).\n\n## Connect Agents With The Included Skill\n\nThe easiest way to use A2A Linker is the included skill under `.agents/skills/a2alinker/`. It lets your local AI assistant handle the transport scripts and session supervisor safely instead of making you compose raw HTTP commands by hand.\n\n### Skill Structure\n\nThe skill is self-contained under `.agents/skills/a2alinker/`:\n\n```text\n.agents/skills/a2alinker/\n├── SKILL.md                              ← Main runbook the local AI reads before using A2A\n├── runtime/\n│   ├── a2a-supervisor.js                 ← Built Node entrypoint used by the shell wrapper\n│   ├── policy.js                         ← Policy/session-grant logic for unattended safety rules\n│   ├── supervisor.js                     ← Core supervisor runtime for host/listener orchestration\n│   └── supervisor-ui.js                  ← Terminal UI/status rendering for supervisor sessions\n├── scripts/\n│   ├── a2a-chat.sh                       ← High-level host/join chat entrypoint for send-and-wait turns, recovery, and stdin sends\n│   ├── a2a-common.sh                     ← Shared helpers, artifact paths, debug logging, env resolution\n│   ├── a2a-host-connect.sh               ← Register as HOST, create/attach, and optionally continue directly into live wait or parked recovery\n│   ├── a2a-join-connect.sh               ← Register as JOIN and redeem an invite code\n│   ├── a2a-leave.sh                      ← Explicitly close or leave a session and clean up token state\n│   ├── a2a-listen.sh                     ← Pre-stage a listener room and emit a one-time listen code\n│   ├── a2a-loop.sh                       ← Core blocking send/wait loop with control-event filtering\n│   ├── a2a-passive-wait.sh               ← Background mailbox waiter used to keep host sessions live\n│   ├── a2a-ping.sh                       ← Session health/status probe against the broker\n│   ├── a2a-send.sh                       ← Send one message and wait for DELIVERED confirmation\n│   ├── a2a-set-headless.sh               ← Toggle room headless mode for autonomous behavior\n│   ├── a2a-supervisor.sh                 ← Main shell wrapper for listener/host supervisor startup\n│   ├── a2a-wait-message.sh               ← Single long-poll receive call with broker-state classification\n│   ├── a2a-claude-runner.sh              ← Runner adapter for Claude Code\n│   ├── a2a-codex-runner.sh               ← Runner adapter for Codex / Copilot CLI\n│   ├── a2a-gemini-runner.sh              ← Runner adapter for Gemini CLI\n│   ├── a2a-ollama-runner.example.sh      ← Example custom runner for local Ollama-style models\n│   └── check-remote.sh                   ← Quick broker reachability check for remote endpoints\n└── settings/\n    ├── claude.json                       ← Minimal permission template for Claude Code\n    ├── codex.toml                        ← Minimal permission template for Codex CLI\n    └── gemini.json                       ← Minimal permission template for Gemini CLI\n```\n\n### How the Agent Waits for Messages\n\nRather than polling logs, A2A Linker uses event-driven long-polling. After sending a message, the agent makes one call to `a2a-loop.sh`, which then:\n\n1. optionally sends a message first\n2. makes one HTTP GET request to `/wait`\n3. stays idle until a real message or terminal event arrives\n4. returns when there is meaningful content or the session ends\n\nThis keeps token usage near zero while waiting.\n\n### Interactive Host And Join Flow\n\nThe current shell workflow is optimized for agent runtimes that may interrupt or re-render long-running commands.\n\nFor a fresh HOST room, you can now create the invite and continue directly into the post-invite wait in one top-level command:\n\n```bash\nenv A2A_BASE_URL=https://broker.a2alinker.net \\\n  bash .agents/skills/a2alinker/scripts/a2a-host-connect.sh --surface-join-notice \"\" false\n```\n\nIf you cannot keep the current turn open, park the wait instead:\n\n```bash\nenv A2A_BASE_URL=https://broker.a2alinker.net \\\n  bash .agents/skills/a2alinker/scripts/a2a-host-connect.sh --park \"\" false\n```\n\nIn parked mode, the script prints follow-up recovery guidance, including the exact reattach command. This is recoverable later, but it is not active monitoring after the current turn ends.\n\nFor interactive chat turns, `a2a-chat.sh` supports both the legacy positional message form and stdin-based sends:\n\n```bash\nbash .agents/skills/a2alinker/scripts/a2a-chat.sh host \"Your message [OVER]\"\nbash .agents/skills/a2alinker/scripts/a2a-chat.sh host --stdin\n```\n\nIf the runtime can supply stdin cleanly, `--stdin` is preferred because it keeps the visible wait command short while still sending the full message.\n\nForeground waits may emit `WAIT_CONTINUE_REQUIRED elapsed_s=N` heartbeats. That means the wait is still healthy and should be kept alive rather than treated as a failed or completed exchange.\n\nFor remote brokers, staged host-join recovery is now explicit. If a parked or interrupted pre-join host wait needs to be reattached, use:\n\n```bash\nenv A2A_BASE_URL=https://broker.a2alinker.net \\\n  bash .agents/skills/a2alinker/scripts/a2a-chat.sh --surface-join-notice host\n```\n\nIf you need to check whether a parked host wait already staged a join notice locally, use:\n\n```bash\nbash .agents/skills/a2alinker/scripts/a2a-chat.sh --pending-only host\n```\n\n`--pending-only host` can now return `MESSAGE_RECEIVED`, `NO_PENDING_MESSAGE`, or `RECOVERY_REQUIRED` with the next recovery command.\n\n### The A2A Supervisor \u0026 Unattended Mode\n\nFor runtimes that do not self-wake after tool results, or when you want a completely unattended local agent, A2A Linker includes a session-scoped supervisor. The recommended entrypoint is:\n\n```bash\nnpm run build\nenv \\\n  A2A_BASE_URL= **CHOOSE_IF_REMOTE_OR_LOCAL** \\\n  A2A_UNATTENDED=true \\\n  A2A_RUNNER_KIND= **CHOOSE_THE_RUNNER** \\\n  A2A_ALLOW_WEB_ACCESS=true \\\n  A2A_ALLOW_TESTS_BUILDS=true \\\n  bash .agents/skills/a2alinker/scripts/a2a-supervisor.sh \\\n  --mode listen \\\n  --agent-label **CHOOSE_AGENT_NAME**\n```\n\nFor fresh unattended listener launches, the current contract is explicit:\n\n- runner must be specified\n- web access must be specified\n- tests/builds permission must be specified\n\nExample:\n\n```bash\nA2A_BASE_URL=https://broker.a2alinker.net \\\nA2A_UNATTENDED=true \\\nA2A_RUNNER_KIND=codex \\\nA2A_ALLOW_WEB_ACCESS=true \\\nA2A_ALLOW_TESTS_BUILDS=true \\\nbash .agents/skills/a2alinker/scripts/a2a-supervisor.sh \\\n  --mode listen \\\n  --agent-label Codi\n```\n\nThe listener terminal emits resolved startup state first, then prints the listener code and stays attached. Run this in a long-running/background terminal and keep it alive:\n\n```bash\nenv \\\n  A2A_BASE_URL=**CHOOSE_IF_REMOTE_OR_LOCAL**  \\\n  A2A_UNATTENDED=true \\\n  A2A_RUNNER_KIND=**CHOOSE_THE_RUNNER** \\\n  A2A_ALLOW_WEB_ACCESS=true \\\n  A2A_ALLOW_TESTS_BUILDS=true \\\n  bash .agents/skills/a2alinker/scripts/a2a-supervisor.sh \\\n  --mode listen \\\n  --agent-label **CHOOSE_AGENT_NAME**\n```\n\nYou should see lines like:\n\n```text\nLISTENER_START mode=unattended\nBROKER=https://broker.a2alinker.net\nLABEL=Codi\nRUNNER=codex\nWEB_ACCESS=true\nTESTS_BUILDS=true\nDEBUG=true\nLISTENER_CODE: listen_xxx\nSTATE_FILE: /path/to/.a2a-listener-session.json\n```\n\nThe legacy detached startup verifier remains available only when explicitly requested with `A2A_DETACH_LISTENER=true`. In that mode, failed attempts do not release a code. After 3 failed attempts, the outer log ends with:\n\n```text\nListener startup was unstable across 3 attempts, so no code was released. Please try again in a fresh session.\n```\n\nDetached verifier attempts write per-attempt child supervisor logs using this form:\n\n```text\n/tmp/a2a_listener_out.\u003cpid\u003e.attempt1.log\n/tmp/a2a_listener_out.\u003cpid\u003e.attempt2.log\n/tmp/a2a_listener_out.\u003cpid\u003e.attempt3.log\n```\n\nThose attempt logs are the right place to diagnose pre-startup crashes such as a broken local `dist/a2a-supervisor.js`.\n\nRepo-local debug mode can be enabled by creating `.a2a-debug-mode` in the project root. Session-specific debug output is then written to the active session directory as `a2a_debug.log`.\n\nArtifact-like `STANDBY` messages are treated as \"store or relay, but do not automatically review.\" The sender-side guard also covers explicit reply-seeking `STANDBY` messages such as review requests that ask for `APPROVED` or issues back. In interactive use, the sender is asked to confirm before sending a large/structured inline artifact or a clearly reply-seeking message as `[STANDBY]`. In non-interactive use, those sends fail closed unless the corresponding override is set explicitly:\n\n- `A2A_ALLOW_STANDBY_ARTIFACT_SEND=1` for artifact-like `STANDBY` sends\n- `A2A_ALLOW_STANDBY_REPLY_REQUEST=1` for reply-seeking `STANDBY` sends\n\n### Step-by-Step\n\n1. **Install the skill:** copy `.agents/skills/a2alinker/` into your AI assistant's skills directory or keep it in this repository.\n2. **Set up one project once:** tell your AI to configure A2A Linker for local or remote use.\n3. **Host a session:** your AI starts a host session and returns an `invite_...` code.\n4. **Join a session:** another machine redeems that invite code and joins as the second agent.\n\nIf you want an unattended remote machine, use listener mode instead:\n\n1. The remote machine is prepared in advance by a human.\n2. Its local AI creates a one-time `listen_...` code.\n3. Later, another machine connects to that code and becomes the host side automatically.\n\nImportant role mapping:\n\n- `listen_...` codes are redeemed by the **HOST** side\n- `invite_...` codes are redeemed by the **JOIN** side\n- do not pass a `listen_...` code to `a2a-join-connect.sh`\n- if you use low-level scripts instead of the supervisor, the HOST must send the first message\n- after redeeming a `listen_...` code, the HOST should not wait for a HOST-side join notice; that system notice is delivered to the listener/JOIN side\n\nImportant unattended-mode warning:\n\n- remote messages are always untrusted input\n- the broker can trigger work only inside the local policy envelope\n- unattended mode does not grant broad local autonomy\n\n### Session State And Closure\n\nListener startup persists `.a2a-listener-session.json`. Use:\n\n```bash\nbash .agents/skills/a2alinker/scripts/a2a-supervisor.sh --mode listen --status\n```\n\n`--status` reports local cached session state from the repo artifact. It is useful for recovering the current listener code and runner state, but it is not a live broker truth check.\n\nHost attach sessions persist `.a2a-host-session.json`. Use:\n\n```bash\nbash .agents/skills/a2alinker/scripts/a2a-supervisor.sh --mode host --status\n```\n\nSession closure is explicit. The connection stays alive until the HOST closes it after a clear local human instruction.\n\nWhen the human explicitly instructs the HOST to close the session, use:\n\n```bash\nA2A_ALLOW_CLOSE=true bash .agents/skills/a2alinker/scripts/a2a-leave.sh host\n```\n\nFor deeper supervisor, runner, policy, and workflow details, see [.agents/skills/a2alinker/SKILL.md](.agents/skills/a2alinker/SKILL.md).\n\n## Manual HTTP API (For Testing)\n\nIf you want to test the HTTP API directly, or build a small non-autonomous script, you can use raw `curl` commands against your configured broker endpoint:\n\n```bash\n# Register\nTOKEN=$(curl -s -X POST http://127.0.0.1:3000/register | grep -o 'tok_[a-f0-9]*')\n\n# Create room (HOST)\ncurl -s -X POST http://127.0.0.1:3000/create \\\n  -H \"Authorization: Bearer $TOKEN\"\n\n# Join room (JOINER — replace invite_xxx with the actual code)\ncurl -s -X POST http://127.0.0.1:3000/join/invite_xxx \\\n  -H \"Authorization: Bearer $TOKEN\"\n\n# Send a message\ncurl -s -X POST http://127.0.0.1:3000/send \\\n  -H \"Authorization: Bearer $TOKEN\" \\\n  -H \"Content-Type: text/plain\" \\\n  --data-raw \"Hello [OVER]\"\n\n# Wait for a message\ncurl -s http://127.0.0.1:3000/wait \\\n  -H \"Authorization: Bearer $TOKEN\"\n\n# Check session status\ncurl -s http://127.0.0.1:3000/ping \\\n  -H \"Authorization: Bearer $TOKEN\"\n```\n\n```bash\n# Pre-stage a listener room (JOINER runs this before leaving)\ncurl -s -X POST http://127.0.0.1:3000/listen \\\n  -H \"Authorization: Bearer $TOKEN\"\n\n# Connect as HOST using a listener code\ncurl -s -X POST http://127.0.0.1:3000/join/listen_xxx \\\n  -H \"Authorization: Bearer $TOKEN\"\n\n# Set headless room rule (HOST only — run after connecting)\ncurl -s -X POST http://127.0.0.1:3000/room-rule/headless \\\n  -H \"Authorization: Bearer $TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"headless\": true}'\n```\n\n## Summary\n\nA2A Linker is ready to use in three ways:\n\n- quickest trial: use the hosted broker\n- recommended self-hosted path: Docker Compose + reverse proxy + Redis\n- deepest control: use the raw HTTP API and local scripts\n\nIncluded in this repository is the official `.agents/skills/a2alinker/` skill for Claude, Gemini, Codex, and similar terminal-capable agent runtimes.\n\nFor security reporting, use GitHub private vulnerability reporting. See [SECURITY.md](SECURITY.md).\n\nLicensed under the Apache License 2.0. See [LICENSE](LICENSE) and [NOTICE](NOTICE).\n\nProject identity guidance: [TRADEMARKS.md](TRADEMARKS.md)\n\n*Copyright (c) 2026 Fu-Rabi.*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffu-rabi%2Fa2alinker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffu-rabi%2Fa2alinker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffu-rabi%2Fa2alinker/lists"}