Files
hermes-agent/plugins/platforms/a2a/plugin.yaml
Eman e42db348c9 fix(plugins): register deferred platform client tools at discovery (#78050)
Rebased onto current main. `hermes_cli/plugins.py` grew 103KB -> 265KB
across 49 commits since the original branch point, and the attribution
mechanism this change hooks into was replaced along the way: the
`_tools_before` / `_plugin_tool_names` snapshot diff is now a
registration ledger sliced from `registration_start`, and `_plugin_id`
is `plugin_key`.

Re-anchored accordingly:

- Discovery-time pre-registration, module reuse, and the `provides_tools`
  opt-in are unchanged.
- Attribution credits `_predeclared_tools` ahead of the ledger slice,
  since those tools registered before `registration_start` and the slice
  cannot see them.
- A failed materialization no longer carries attribution across. The
  failure path now sweeps the whole ownership ledger for the plugin key,
  not just the `registration_start:` slice, so the pre-registered tools
  are disposed along with the adapter. Attribution and the registry now
  agree at zero instead of reporting tools the process is not serving.

tests/hermes_cli/test_deferred_platform_client_tools.py 13/13.
test_plugins.py, test_plugins_cmd_list.py, test_plugin_cli_registration.py
65/65.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 21:56:33 -07:00

71 lines
3.3 KiB
YAML

name: a2a-platform
label: A2A
kind: platform
version: 1.0.0
description: >
A2A (Agent-to-Agent) protocol v1.0 support for Hermes Agent — both directions
of the open Linux Foundation standard for inter-agent communication.
OUTBOUND (client tools): a2a_discover, a2a_call, a2a_list, a2a_history, and
a2a_orchestrate let the agent fetch another agent's Agent Card and send it
tasks over JSON-RPC — works with any A2A-compliant peer (Hermes, LangChain,
CrewAI, Google ADK, OpenClaw, ...).
INBOUND (platform adapter): exposes Hermes as an A2A-discoverable agent. An
Agent Card is served at /.well-known/agent-card.json (v1.0 canonical path;
legacy agent.json also answers) and incoming tasks are routed
into the agent's live gateway session like any other platform — so the agent
that replies is the same one talking to its user, with full memory and
context, not a throwaway clone.
Security is on by default: no bearer token configured => localhost-only bind.
Inbound task text passes through prompt-injection filters; outbound text is
scrubbed of credential-shaped strings; every exchange is audit-logged and
persisted to disk outside the context-compaction pipeline so conversations
survive compaction and restarts.
Pure stdlib transport (http.server + urllib) — no a2a-sdk dependency required.
author: Nous Research
# The outbound client tools. Declaring them here is what asks discovery to
# import `tools.py` in CLI/TUI processes, where the plugin is otherwise
# deferred and the tools would never register at all (#78050). The inbound
# adapter stays deferred either way — only this submodule is imported.
provides_tools:
- a2a_discover
- a2a_call
- a2a_list
- a2a_history
- a2a_orchestrate
# requires_env / optional_env are surfaced in the `hermes config` UI via the
# platform-plugin env var injector in hermes_cli/config.py.
requires_env: []
optional_env:
- name: A2A_PEER_TOKENS
description: "Per-peer bearer tokens ('alice:tok1,bob:tok2'). Each remote agent gets its own credential; the matched name is the authenticated identity used for rate limiting, trust, and audit."
prompt: "A2A per-peer tokens (name:token, comma-separated; or empty)"
password: true
- name: A2A_BEARER_TOKEN
description: "Shared bearer token for inbound A2A calls (identity falls back to caller IP). With no token of any kind => bind to 127.0.0.1 only (no remote access)."
prompt: "A2A shared bearer token (or empty for localhost-only)"
password: true
- name: A2A_HOST
description: "Inbound bind host. Defaults to 127.0.0.1; only widens to 0.0.0.0 when a bearer token is set AND you opt in here."
prompt: "A2A bind host (default 127.0.0.1)"
password: false
- name: A2A_PORT
description: "Inbound A2A server port (default 9900)."
prompt: "A2A port (default 9900)"
password: false
- name: A2A_AGENT_NAME
description: "Name advertised on this agent's Agent Card (default: hostname-derived)."
prompt: "A2A agent name"
password: false
- name: A2A_ALLOW_ALL_USERS
description: "Allow any authenticated A2A peer to reach the agent (dev only)."
prompt: "Allow all A2A peers? (true/false)"
password: false
- name: A2A_HOME_CHANNEL
description: "Task/context id used as the cron / notification delivery target for deliver=a2a."
prompt: "A2A home channel (or empty)"
password: false