docs(a2a): client exposures, URLs without queries, README/architecture
This commit is contained in:
23
docs/a2a.md
23
docs/a2a.md
@@ -64,6 +64,10 @@ malformed task file is read as "no such task" (`TaskNotFound`) without a log lin
|
||||
Without it: name from `A2A:Card:Name`, description from the first non-empty line of the workspace's `PERSONA.md`
|
||||
(else `A2A:Card:Description`), and one generic `chat` skill.
|
||||
|
||||
The [client](#client) keeps its own files in the same directory: `agents.json` (the agents this workspace's assistant
|
||||
may call, with their keys; see [agents.json](#agentsjson)) and `pending.json` (its watches of remote tasks; see
|
||||
[Watches](#watches)).
|
||||
|
||||
`tasks/<taskId>.json`: one task per file (the SDK's `AgentTask` plus which caller owns it and its push configs),
|
||||
written atomically (temp file, then rename) and read fresh on every request.
|
||||
|
||||
@@ -154,7 +158,11 @@ zone into its sessions (`docs/telegram-bot.md#a2a`); a host that embeds the libr
|
||||
- reading `.volcanic/a2a/callers.json` — every caller's plaintext key — and editing it, i.e. minting itself (or
|
||||
anyone) new keys or changing other callers' entries;
|
||||
- writing `.volcanic/scheduler/jobs.json` or `.volcanic/triggers/triggers.json`, whose prompts later run in the
|
||||
owner's **main** session — the one that has the calendar and the owner's history.
|
||||
owner's **main** session — the one that has the calendar and the owner's history;
|
||||
- with the [client](#client) on, forging `.volcanic/a2a/pending.json`: a record with an `undelivered` text runs as a
|
||||
prompt in the owner's chat on the next restart or session start;
|
||||
- editing `.volcanic/a2a/agents.json` to point an agent name somewhere else, so the owner's next `send` to that
|
||||
name — message, attachments and the configured key — goes there (and reading the keys in it).
|
||||
|
||||
These are accepted v1 exposures: the owner chose plain files with no protection. Give A2A keys only to agents you
|
||||
would trust with that workspace.
|
||||
@@ -215,7 +223,8 @@ Off (the default), no session gets the tool, no watches are restored, and `/a2a`
|
||||
|
||||
Only the owner's own chats get the `a2a` tool: the Telegram host adds `A2AClientExtension` to each allowed chat's
|
||||
session (target = the chat id), never host-wide. So the isolated sessions the server opens for inbound A2A callers
|
||||
(untrusted) can't use the keys in `agents.json` to call other agents. The startup log shows
|
||||
(untrusted) can't call other agents through the tool (their `bash` can still read the keys in `agents.json`; see
|
||||
[Client security](#client-security)). The startup log shows
|
||||
`A2A client: on, agents in each chat's .volcanic/a2a/agents.json, watches subscribe or poll` (or `push at <url>`).
|
||||
|
||||
### agents.json
|
||||
@@ -350,8 +359,10 @@ configured subscribes instead. On shutdown the watches stop and their records st
|
||||
Every outgoing message carries `metadata["volcanic.hops"]` = the session's inbound hop count + 1. The count comes from
|
||||
the `a2a.inbound` event the server's per-session extension emits before each inbound prompt; a session with no inbound
|
||||
A2A counts 0. A Volcanic server refuses a task over its `MaxHops` (3), which stops two assistants delegating to each
|
||||
other forever. In Telegram only the owner's chats have the tool, so their messages always carry 1; the listener
|
||||
matters for hosts that add the extension to sessions that also receive A2A.
|
||||
other forever. In Telegram only the owner's chats have the tool, so their messages always carry 1 and the listener is
|
||||
inactive: the remote side's `MaxHops` (or whatever guard a non-Volcanic remote has) is the only thing that bounds a
|
||||
chain of agents delegating onwards. The listener matters for hosts that add the extension to
|
||||
sessions that also receive A2A.
|
||||
|
||||
### Client configuration
|
||||
|
||||
@@ -372,6 +383,10 @@ ignores any configured value otherwise.
|
||||
|
||||
- **`agents.json` keys are plaintext in the workspace**, like `callers.json`: anything that reads the workspace (the
|
||||
agent's `bash`, an inbound A2A caller's isolated session, a backup) can read them.
|
||||
- **An inbound A2A caller's isolated session can tamper with the client's files** through `bash` in the shared
|
||||
workspace: forge `pending.json` (an `undelivered` text runs as a prompt in the owner's chat on restart or session
|
||||
start) or redirect an agent name in `agents.json` (the owner's next `send`, its attachments and the key go to the new
|
||||
URL). Accepted v1 exposures, like `jobs.json` (see [Security](#security)).
|
||||
- **The agent chooses where data goes.** It can edit `agents.json` like any workspace file, so it can add an agent with
|
||||
any URL (including internal addresses; the client's HTTP has no private-range guard) and send it workspace files.
|
||||
That is the same trust it already has through `bash` (`curl`), not a new boundary; treat the `a2a` tool accordingly.
|
||||
|
||||
Reference in New Issue
Block a user