The shape rule (a platform prefix plus _TOKEN/_SECRET/_PASSWORD/_KEY) also matched variables Hermes never reads: the platform list holds plain words (LOCAL, GATEWAY, WEBHOOK, SLACK), so a user's SLACK_USER_TOKEN, LOCAL_LLM_API_KEY or GATEWAY_API_KEY vanished from the terminal and terminal.env_passthrough could not bring them back. The prefix census it leaned on also failed open (an unreadable plugins dir cached an empty set). Adapter secrets now come from what adapters declare: password entries of the messaging OPTIONAL_ENV_VARS (built-ins plus every platform plugin manifest) and secret-named keys of the gateway env-override table, both Tier 1 and refused by passthrough; plus the secret-named required_env of adapters registered in the current profile scope, read per spawn without loading deferred adapters, Tier 2 only because required_env is an unchecked setup list. Secrets nothing declared get a manifest entry (TELEGRAM_WEBHOOK_SECRET, PHOTON_SIDECAR_TOKEN, A2A_PUSH_SECRET, TEAMS_GRAPH_ACCESS_TOKEN, TEAMS_INCOMING_WEBHOOK_URL) or join the policy's read-in-code list (QQ_STT_API_KEY, the two MSGRAPH names).
75 lines
3.5 KiB
YAML
75 lines
3.5 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_PUSH_SECRET
|
|
description: "HMAC secret for signing push notifications (default: the shared bearer token)."
|
|
prompt: "A2A push signing secret (or empty)"
|
|
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
|