Warning
hermes-a2a-bridge has been retired. Hermes Agent now ships native A2A support
as a gateway platform and a2a toolset, replacing this standalone bridge:
- Outbound — call any A2A peer with
a2a_discover,a2a_call,a2a_history,a2a_orchestrate. - Inbound — Agent Card, JSON-RPC 2.0, SSE streaming, push notifications (HMAC-signed).
- Safer — per-peer tokens, prompt-injection filtering, audit log, anti-loop turn caps.
- Verified — interoperates with the official
a2a-sdk.
If you're setting up agent-to-agent communication today, use the built-in A2A instead: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/a2a
This repository is kept read-only for historical reference. No further releases, fixes, or support are planned. The code's ideas graduated into Hermes Agent itself.
MCP lets your AI tie its own shoes. A2A lets it call another AI for help when the shoes get complicated.
hermes-a2a-bridge is a thin, local-first bridge that lets Hermes Agent call other agents and expose itself as one too — HTTP+JSON, text and structured data parts, SSE streaming, durable replay, the works. It's an A2A-shaped surface: it talks the Google A2A protocol well enough to have a real conversation, but if you walk in expecting full compliance badges, you're going to be disappointed. We call that honest, not incomplete.
Current version: v0.5.0.
Made by @tonysimons_ — building things so your agents don't have to text each other in DMs.
Python 3.11 or newer is required.
python -m pip install -e .The package exposes the hermes_agent.plugins entry point a2a-bridge = hermes_a2a_bridge. Enable that plugin in Hermes before running hermes a2a init.
Check the package entry point and Hermes activation status with the read-only install doctor:
hermes-a2a-bridge doctor-install
hermes-a2a-bridge doctor-install --json
python -m hermes_a2a_bridge doctor-install --jsonThe helper does not edit user config. It reports whether the package imports, whether the hermes_agent.plugins entry point is installed, whether a hermes executable is on PATH, and whether a readable Hermes config already lists a2a-bridge under plugins.enabled.
Hermes Agent v0.17.0 has a host-side discovery gap for pip entry-point plugins: the runtime loader can load hermes_agent.plugins entry points, but hermes plugins list and hermes plugins enable a2a-bridge only discover directory-based bundled/user plugins. In that host version, enable this package by adding the entry-point name to plugins.enabled in ~/.hermes/config.yaml:
plugins:
enabled:
- a2a-bridgeAfter the next Hermes process starts, the host should mount hermes a2a ..., register the a2a_bridge toolset, and load the bundled a2a-bridge skill from the installed package. If hermes a2a --help still says a2a is an invalid command, verify that the same Python environment running hermes can see the package entry point:
python -c "import importlib.metadata as m; print([(e.name, e.value) for e in m.entry_points().select(group='hermes_agent.plugins')])"The upstream Hermes Agent hermes plugins list/enable discovery improvement for pip entry-point plugins is pending separately; this bridge release does not depend on that upstream change. Manual plugins.enabled configuration is the documented and supported activation path.
hermes a2a setup
hermes a2a status
hermes a2a maintenance doctor --json
hermes a2a card --json
hermes a2a serve
curl http://127.0.0.1:8765/.well-known/agent-card.jsonhermes a2a setup explicitly creates ~/.hermes/a2a/config.yaml and ~/.hermes/a2a/tasks.sqlite3; init remains available as a compatibility alias. hermes a2a status is read-only and reports local task, event, registry, and SQLite operational counts. By default the bridge binds to 127.0.0.1:8765, requires bearer auth for task endpoints, and uses the verified one-shot argv:
GET /health/live and GET /health/ready are unauthenticated liveness/readiness probes. GET /status requires the bearer token and returns safe task and queue counts only. hermes a2a maintenance doctor is read-only: it checks SQLite metadata, loaded configuration, durable event state, and lease expiry without pruning, recovery, or cancellation expiry.
For retried message:send or message:stream requests, send an Idempotency-Key header (maximum 256 characters). The bridge deterministically reuses one durable task and never stores or returns the raw key. Named registry peers cache their verified Agent Card endpoint for 60 seconds; the cache contains no token and is invalidated on registry add/update/remove.
hermes chat -q {prompt}
If you set executor.command: null, tasks fail cleanly with:
No Hermes executor command configured. Set executor.command in ~/.hermes/a2a/config.yaml
For short remote jobs, use send --wait to poll until a terminal state, or send --follow to submit through the peer's SSE stream and print updates as they arrive. --wait accepts bounded --timeout and --poll-interval values; --follow and --wait are mutually exclusive.
hermes a2a send peer "review this patch" --wait --timeout 120
hermes a2a send peer "review this patch" --followBefore sending messages or streaming to a remote agent, check compatibility:
# Metadata-only: reads the remote Agent Card, classifies compatibility
hermes a2a doctor https://agent.example --json
# Opt-in live probe: sends one diagnostic text message via message:send
hermes a2a doctor https://agent.example --live-probe --json
# Opt-in stream probe: also sends one diagnostic via message:stream, reads bounded SSE
hermes a2a doctor https://agent.example --live-probe --stream-probe --json- Metadata-only is the default. It fetches the peer Agent Card only and reports whether the advertised metadata looks compatible with Hermes' HTTP+JSON 1.x subset. No messages are sent.
- Live probe (
--live-probe) sends one small diagnostic text message and attemptsGET /tasks/{task_id}if the send response includes a task ID. Requires explicit opt-in. - Stream probe (
--stream-probe) requires--live-probe. Sends one diagnostic text message throughmessage:stream, reads a bounded SSE response (default 10s timeout, 20 events max). Requires explicit opt-in.--stream-probewithout--live-probeis skipped. - These probes do not send files, fetch files, subscribe, cancel, mutate registry state, or prove full A2A conformance.
The same checks are available as a Hermes tool (a2a_doctor_peer) with live_probe and stream_probe boolean arguments.
A fast, local-only fake A2A peer is included under tests/ for diagnostics and release validation. It responds immediately to Agent Card discovery, message:send, message:stream, and task lookup without calling a real executor.
python -m tests.local_http_json_peer --host 127.0.0.1 --port 8766Then run Peer Doctor against it:
hermes a2a doctor http://127.0.0.1:8766 --json
hermes a2a doctor http://127.0.0.1:8766 --live-probe --json
hermes a2a doctor http://127.0.0.1:8766 --live-probe --stream-probe --json- This peer is test/dev-only and local-only. It binds to
127.0.0.1by default and refuses non-loopback binds unless you pass--allow-remote. - It does not send files, fetch files, read arbitrary local paths, or shell out to a real executor.
- It is useful for verifying that Peer Doctor metadata, live probe, and stream probe work without the default
hermes chat -qexecutor timeout. - It is not proof of interoperability with a real remote peer.
- Source checkout required:
tests/is excluded from the built wheel/sdist (pruned byMANIFEST.in). To use the fake peer, clone the repo and run from the project root.
hermes a2a serveExample config snippet:
server:
host: 127.0.0.1
port: 8765
public_url: http://127.0.0.1:8765
require_auth: true
allow_remote_hosts: false
executor:
command:
- hermes
- chat
- -q
- "{prompt}"
cancel_grace_seconds: 3
retention:
max_events_per_task: 500
max_event_age_days: 30
prune_on_startup: true
recovery:
stale_task_after_seconds: 900
recover_on_startup: true
stale_working_state: TASK_STATE_FAILED
ownership:
lease_seconds: 60
heartbeat_interval_seconds: 10
recover_expired_leases_on_startup: true
expired_lease_state: TASK_STATE_FAILED
sqlite:
busy_timeout_ms: 5000
journal_mode: WAL
synchronous: NORMAL
maintenance_vacuum: false
cancellation:
request_ttl_seconds: 300
poll_interval_seconds: 0.5
observability:
lease_warning_seconds: 20
include_diagnostics_in_stats: true
faults:
sqlite_retry_attempts: 3
sqlite_retry_backoff_seconds: 0.05
streaming:
poll_interval_seconds: 0.5
max_replay_events: 1000
replay_gap_status_code: 409
replay_gap_error_code: replay_gap
parts:
max_data_part_bytes: 65536
allow_data_parts: true
allow_file_parts: false
allow_file_id_references: false
allow_remote_url_file_references: false
allow_inline_file_bytes: false
files:
storage_dir: "~/.hermes/a2a/files"
max_file_bytes: 10485760
max_total_storage_bytes: 1073741824
allowed_mime_types:
- "text/plain"
- "application/json"
- "text/markdown"
- "text/csv"
- "application/pdf"
- "image/png"
- "image/jpeg"
reject_unknown_mime: true
allow_remote_url_references: true
auto_fetch_remote_urls: false
allow_inline_bytes: false
max_inline_bytes: 0
cleanup_deleted_task_files: false
shard_depth: 2
artifacts:
parse_json_output: true
max_artifact_data_bytes: 65536Read the generated bearer token locally from ~/.hermes/a2a/config.yaml, then:
curl http://127.0.0.1:8765/health
curl http://127.0.0.1:8765/.well-known/agent-card.json
curl -X POST http://127.0.0.1:8765/message:send \
-H "Authorization: Bearer $A2A_TOKEN" \
-H "Content-Type: application/json" \
-H "A2A-Version: 1.0" \
-d '{"message":{"messageId":"replace-with-a-uuid","role":"ROLE_USER","parts":[{"text":"Hello","mediaType":"text/plain"}]}}'
curl -X POST http://127.0.0.1:8765/message:send \
-H "Authorization: Bearer $A2A_TOKEN" \
-H "Content-Type: application/json" \
-H "A2A-Version: 1.0" \
-d '{"message":{"messageId":"replace-with-a-uuid","role":"ROLE_USER","parts":[{"data":{"topic":"status","count":2}}]}}'
curl -X POST http://127.0.0.1:8765/message:send \
-H "Authorization: Bearer $A2A_TOKEN" \
-H "Content-Type: application/json" \
-H "A2A-Version: 1.0" \
-d '{"message":{"messageId":"replace-with-a-uuid","role":"ROLE_USER","parts":[{"text":"Summarize this","mediaType":"text/plain"},{"data":[{"name":"Ada"},{"name":"Grace"}]}]}}'
curl -N -X POST http://127.0.0.1:8765/message:stream \
-H "Authorization: Bearer $A2A_TOKEN" \
-H "Content-Type: application/json" \
-H "A2A-Version: 1.0" \
-d '{"message":{"messageId":"replace-with-a-uuid","role":"ROLE_USER","parts":[{"text":"Hello","mediaType":"text/plain"}]}}'
curl -H "Authorization: Bearer $A2A_TOKEN" \
http://127.0.0.1:8765/taskshermes-a2a-bridge doctor-install [--config PATH] [--json]
hermes a2a init
hermes a2a setup [--json]
hermes a2a status [--json]
hermes a2a card [--json]
hermes a2a serve [--host HOST] [--port PORT]
hermes a2a token rotate [--show-token] [--json]
hermes a2a discover URL [--json]
hermes a2a doctor AGENT_OR_URL [--token TOKEN] [--timeout N] [--live-probe] [--live-probe-message TEXT] [--stream-probe] [--stream-probe-timeout N] [--stream-probe-max-events N] [--json]
hermes a2a registry add NAME URL [--token TOKEN] [--json]
hermes a2a registry list [--json]
hermes a2a registry remove NAME [--json]
hermes a2a files ingest PATH [--task-id TASK_ID] [--artifact-id ARTIFACT_ID] [--name NAME] [--mime-type MIME] [--metadata-json JSON] [--json]
hermes a2a files add-url URL [--name NAME] [--mime-type MIME] [--size-bytes N] [--sha256 SHA256] [--task-id TASK_ID] [--artifact-id ARTIFACT_ID] [--metadata-json JSON] [--json]
hermes a2a files list [--task-id TASK_ID] [--artifact-id ARTIFACT_ID] [--limit N] [--json]
hermes a2a files show FILE_ID [--json]
hermes a2a files delete FILE_ID [--delete-bytes] [--json]
hermes a2a files attach-artifact FILE_ID TASK_ID [--artifact-id ARTIFACT_ID] [--name NAME] [--json]
hermes a2a files fetch-metadata FILE_ID --agent AGENT_OR_URL [--token TOKEN] [--json]
hermes a2a files download FILE_ID OUTPUT_PATH --agent AGENT_OR_URL [--token TOKEN] [--json]
hermes a2a files verify FILE_ID [--json]
hermes a2a files scan [--json]
hermes a2a files cleanup-orphans [--dry-run] [--confirm] [--json]
hermes a2a files repair [--dry-run] [--confirm] [--json]
hermes a2a files stats [--json]
hermes a2a maintenance stats [--json]
hermes a2a maintenance doctor [--json]
hermes a2a maintenance prune-events [--json]
hermes a2a maintenance recover-stale [--json]
hermes a2a maintenance leases [--json]
hermes a2a maintenance cancellations [--json]
hermes a2a maintenance recover-leases [--json]
hermes a2a send AGENT_OR_URL MESSAGE [--file-id FILE_ID]... [--token TOKEN] [--wait | --follow] [--timeout N] [--poll-interval N] [--json]
hermes a2a stream AGENT_OR_URL MESSAGE [--file-id FILE_ID]... [--token TOKEN] [--json]
hermes a2a subscribe TASK_ID [--agent AGENT_OR_URL] [--token TOKEN] [--last-event-id ID] [--json]
hermes a2a tasks [--agent AGENT_OR_URL] [--token TOKEN] [--json]
hermes a2a task TASK_ID [--agent AGENT_OR_URL] [--token TOKEN] [--json]
hermes a2a cancel TASK_ID [--agent AGENT_OR_URL] [--token TOKEN] [--json]
For example:
hermes a2a stream demo "Summarize the current task" --json
hermes a2a send demo "Summarize the staged report" --file-id file_abcdefghijklmnopqrstuv --json
hermes a2a stream demo "Summarize the staged report" --file-id file_abcdefghijklmnopqrstuv --json
hermes a2a subscribe TASK_ID --agent demo --json
hermes a2a subscribe TASK_ID --agent demo --last-event-id 12 --json
hermes a2a doctor demo --json
hermes a2a doctor demo --live-probe --json
hermes a2a doctor demo --live-probe --stream-probe --jsonNotes:
--jsonprints JSON only.hermes-a2a-bridge doctor-installis a standalone package helper; it is available before the Hermes host mountshermes a2a ....registry list --jsonreportshasTokenand never prints token values.--file-idappends stored file ID reference parts only, shaped as{ "file": { "fileId": "file_..." } }. The target server must explicitly enable bothparts.allow_file_parts: trueandparts.allow_file_id_references: true.send --fileandstream --fileare not supported. The CLI does not read local files, stage files automatically, fetch remote URLs, or embed file bytes for send/stream requests.send --waitpolls a remote task until it reaches a terminal state;send --followopens the remotemessage:streamendpoint and renders bounded SSE updates. They are mutually exclusive.token rotatedoes not print the new token unless--show-tokenis used.
Hermes can stage local files and record metadata-only remote URL references through explicit CLI commands. These are local operations only; inbound A2A file parts remain closed by default.
# Stage a local file into controlled storage
hermes a2a files ingest ./report.txt --json
# Record a metadata-only remote URL reference (no fetch, no HEAD, no download)
hermes a2a files add-url https://example.com/report.pdf --name report.pdf --mime-type application/pdf --json
# Attach an already-staged file to a task artifact
hermes a2a files attach-artifact FILE_ID TASK_ID --json
# List, inspect, verify, scan, and maintain staged files
hermes a2a files list --json
hermes a2a files show FILE_ID --json
hermes a2a files verify FILE_ID --json
hermes a2a files scan --json
hermes a2a files stats --json
# Authenticated local file routes (require bearer token)
curl -H "Authorization: Bearer $A2A_TOKEN" \
http://127.0.0.1:8765/files/FILE_ID/metadata
curl -H "Authorization: Bearer $A2A_TOKEN" \
-OJ http://127.0.0.1:8765/files/FILE_ID
# Clean up orphaned bytes or repair missing-byte metadata (dry-run by default)
hermes a2a files cleanup-orphans --dry-run
hermes a2a files repair --dry-runCurrent file boundaries:
- Inbound file parts are closed by default.
parts.allow_file_parts: falseandparts.allow_file_id_references: false. - When both gates are enabled, only pre-staged local stored file ID references (
{ "file": { "fileId": "file_..." } }) are accepted on/message:sendand/message:stream. - No inline bytes, no arbitrary local paths, no remote URL inbound references, no uploads, no auto-fetching.
- CLI
send --file-idandstream --file-idconstruct stored-ID reference parts only. They do not read files, fetch URLs, or embed bytes. files.auto_fetch_remote_urlsremainsfalseby default. Metadata-only URL references are inert records.- The Agent Card defaults to quiet (text/JSON modes only) and only advertises file references when both stored-ID gates are enabled — and even then, only for pre-staged local IDs.
Full details: docs/FILE_BOUNDARY_STATUS.md. Design history: docs/FILE_PARTS_DESIGN.md, docs/INBOUND_FILE_PARTS_DESIGN.md.
Registered tools:
a2a_discover_agenta2a_doctor_peera2a_send_messagea2a_get_taska2a_list_tasksa2a_cancel_taska2a_registry_adda2a_registry_lista2a_registry_remove
Behavior:
- Every tool returns a JSON string.
- Successful tool responses use
success: true. - Failed tool responses use
success: falseand redact bearer tokens. - Registry list responses report
hasTokenonly. a2a_doctor_peeraccepts a registry name or URL. By default it is metadata-only.live_probe: truesends one diagnosticmessage:send;live_probe: true, stream_probe: truesends one diagnosticmessage:streamand reads a bounded SSE response.stream_probe: truewithoutlive_probe: trueis skipped.- Remote send/get/cancel responses include
taskandresultTextwhen available. Structured artifacts are returned unchanged. a2a_send_messageaccepts a stringmessage, optional structureddata(object/array), and optionalfile_ids: ["file_..."]for stored file ID references only. No paths, URLs, URIs, inline bytes, or raw content.- Live SSE is not exposed as a Hermes tool. Streaming remains available through the CLI and Python client.
- The server binds to
127.0.0.1by default. - Non-local binds are refused unless
server.allow_remote_hosts: trueis explicitly set. /healthand/.well-known/agent-card.jsonare public; task endpoints require bearer auth by default.- Tokens are never included in the Agent Card, registry list output, default CLI token rotation output, tool errors, or server errors.
text/plaintext parts and structured JSON data parts are accepted. File parts, binary blobs, URI file references, image/audio/video parts, push notifications, OAuth, and public tunneling are intentionally out of scope.- Incoming file parts are supported only for pre-staged local stored file ID references when both stored-ID gates are enabled. Defaults remain closed.
- The executor runs argv directly without a shell.
- Remote Agent Cards and responses should be treated as untrusted input.
This bridge is a deliberately bounded HTTP+JSON 1.0 subset. It is not full A2A conformance.
What works:
- Discovery, text and structured JSON data send/stream, task lookup, cancel, subscribe, durable replay
- Black-box interop with official
a2a-sdk1.0.3 and 1.1.0 (isolated temp interpreters, not runtime deps) - Structured JSON data parts and artifacts compatible with official SDK
Partshape - Gated stored local file ID references (Hermes-specific, closed by default)
- Peer Doctor diagnostics (metadata-only by default; live/stream probes are explicit opt-in)
What is intentionally unsupported:
/v1routes, JSON-RPC runtime, gRPC- OAuth, signed Agent Cards, public tunneling
- Inline bytes, arbitrary local path reads, remote URL fetching, upload routes
- CLI
send --file,stream --file - Full A2A conformance claims
Detailed version history, black-box evidence, and SDK deviation ledger: docs/INTEROP.md. External peer search notes: docs/EXTERNAL_INTEROP.md.
| Capability | Status |
|---|---|
| Agent Card | Yes |
HTTP+JSON /message:send |
Yes |
HTTP+JSON /message:stream |
Yes, SSE |
| Text parts | Yes |
| Data parts | Yes, JSON object/array with size limits |
| Structured artifacts | Yes |
| Streaming data artifact updates | Yes |
GET /tasks/{id} |
Yes |
GET /tasks |
Yes |
| Cancel task | Yes (local subprocess only) |
| Subscribe task | Yes |
| Durable replay | Yes, local SQLite |
Last-Event-ID resume |
Yes |
| Replay-gap detection | Yes |
| Retention controls | Yes |
| Stale task recovery | Yes |
| Ownership leases | Yes |
| Cooperative cancellation | Yes, SQLite-coordinated |
| Local file staging CLI | Yes, local metadata/storage only |
| Authenticated local file routes | Yes, staged files only |
| Stored file artifact references | Yes, Hermes-owned staged files only |
| Metadata-only remote URL references | Yes, local CLI only; no fetch |
| File parts | Stored local file IDs only, gated off by default |
| Multimodal parts | No |
| OAuth | No |
| JSON-RPC | No |
| gRPC | No |
| Signed Agent Cards | No |
| Public tunnel setup | No |
| Full A2A compliance claim | No |
- Text parts and bounded structured JSON data parts are supported. File parts are gated and closed by default.
- Streaming uses Server-Sent Events over local HTTP+JSON. Every event gets a local SQLite event ID before emission.
- Durable replay survives server restarts with the same database. Pruning can invalidate old resume cursors (returns
409 replay_gap). - Live fan-out buffers are bounded and process-local. Cross-process updates use SQLite polling, not a distributed message bus.
- Queued tasks can be canceled before execution. Cancellation terminates the subprocess owned by the current server process; a different server process writes a cooperative request but does not kill PIDs across ownership boundaries.
- Registry tokens are stored in local SQLite, not an encrypted secret store.
- Stored file artifact references are local-first evidence, not broad external file interoperability. Official SDK 1.1.0/1.0.3 stored-ID send is unsupported because those models reject nested
fileobjects. - Public no-auth stored-ID peer capture is still absent.
| What you need | Read |
|---|---|
| Install, enable, quickstart, examples | This README |
| Agent-friendly orientation, boundaries, common tasks | AGENTS.md |
| A2A compatibility ledger, SDK evidence, deviations | docs/INTEROP.md |
| External peer search history, raw capture harness | docs/EXTERNAL_INTEROP.md |
| File boundary audit (routes, config, Agent Card, what's closed) | docs/FILE_BOUNDARY_STATUS.md |
| File-part design history (phases 1-10, storage design) | docs/FILE_PARTS_DESIGN.md |
| Inbound file-part design (gates, shapes, rejection audit) | docs/INBOUND_FILE_PARTS_DESIGN.md |
| Release validation checklist | docs/RELEASE_CHECKLIST.md |
| Hermes tool usage guidance | hermes_a2a_bridge/skills/a2a-bridge/SKILL.md |
| Contributing rules and boundaries | CONTRIBUTING.md |
Event history is retained independently from task and registry rows. By default, startup keeps the newest 500 events per task and removes events older than 30 days. Pruning never deletes tasks or registry entries.
Before execution, a server instance acquires a SQLite ownership lease for the task. While the subprocess runs, the server refreshes that lease every ownership.heartbeat_interval_seconds. A second instance cannot acquire an unexpired lease.
Lease diagnostics report lease age, heartbeat age, seconds until expiry, owner instance/PID, task state, and warning flags. The warning threshold is controlled by observability.lease_warning_seconds.
On startup, expired leases are recovered and their non-terminal tasks are marked failed. Disable with ownership.recover_expired_leases_on_startup: false.
hermes a2a maintenance stats
hermes a2a maintenance prune-events --json
hermes a2a maintenance recover-stale --json
hermes a2a maintenance leases --json
hermes a2a maintenance cancellations --json
hermes a2a maintenance recover-leases --jsonstats reports task, event, registry, lease, and file-attachment metadata counts; active, expired, and stale-heartbeat lease totals; pending and expired cancellation totals; event-ID bounds; database path and size; journal mode; busy timeout; SQLite warning count; and retry counters.
SQLite connections request busy_timeout, WAL journaling, and NORMAL synchronous mode by default. Event writes, lease writes, cancellation writes, and task-state updates retry transient busy/locked failures using bounded faults.sqlite_retry_* settings. Permanent SQL errors are not swallowed.
Event IDs belong to one SQLite database. No external broker is required: active subscriptions poll that database, deduplicate against local live notifications, and cap replay queries. WAL, retries, leases, and cooperative requests improve local multi-process behavior but are not production clustering.
hermes plugins enable a2a-bridgesays the plugin is missing: Runhermes-a2a-bridge doctor-installto verify the package entry point, then adda2a-bridgetoplugins.enabledin~/.hermes/config.yamlon Hermes Agent v0.17.0. This is a host plugin-manager discovery limitation for pip entry points, not a package entry-point registration failure.hermes a2a --helpsaysa2ais an invalid command: Confirmplugins.enabledincludesa2a-bridgeand start a new Hermes process.hermes-a2a-bridge doctor-install --jsoncan report the best-effort activation status for agents. The CLI command is mounted only after the host runtime loader enables the entry-point plugin.hermes a2a serverefuses a bind host: Keep127.0.0.1or setserver.allow_remote_hosts: trueexplicitly.- Remote calls fail with auth errors: Check that the target bearer token was provided explicitly or saved in the registry entry.
- Tasks fail immediately with executor configuration errors:
Set
executor.commandto an argv list containing{prompt}. python -m pipworks butpipdoes not: Usepython -m pipin environments wherepipis not onPATH.
CI currently tests Python 3.11, 3.12, and 3.13 on Ubuntu, plus Python 3.11 on Windows. Optional official SDK tests require an explicitly configured isolated A2A_SDK_PYTHON interpreter and skip during normal runs when it is not set.
python -m pip install -e ".[test]"
python -m pytest
python -m compileall -q hermes_a2a_bridge tests
python -m buildDo not broaden file support or make full A2A conformance claims without a design pass, tests, and docs.
