jcp-gateway: a task's exchanges and an interim result's retry are decided as continuations of the call #336
3 changed files with 1192 additions and 44 deletions
48
jcp/SPEC.md
48
jcp/SPEC.md
|
|
@ -1049,6 +1049,53 @@ before the field existed.
|
|||
exercise any capability from a `data` frame (§7), regardless of its content. Tool
|
||||
and agent outputs MUST be tagged `data`.
|
||||
|
||||
### 6.1 Continuations: work that answers later (REQUIRED where an enforcement point relays it)
|
||||
|
||||
An endpoint may answer a request before its work is done. It may return a
|
||||
**handle** to work that goes on, whose outcome the client fetches in later
|
||||
exchanges that name the handle (MCP's tasks; an A2A task). Or it may return an
|
||||
**interim result** asking the client for input, which the client answers by
|
||||
repeating the request with its answers attached (MCP's `input_required`). Each
|
||||
later exchange moves the first request's work and the first request's kind of
|
||||
payload: the outcome is the action's output, and the answers go to the
|
||||
endpoint as its arguments do. So an enforcement point that relays such
|
||||
exchanges and treats the later ones as discovery has a door beside its gate.
|
||||
Such an enforcement point:
|
||||
|
||||
1. MUST decide each later exchange as a **continuation** of the first: against
|
||||
the grant the first was decided on, at the moment the later exchange is
|
||||
made, so a grant revoked, expired or spent since refuses it (§7), and the
|
||||
outcome of work the grant no longer covers is not fetched under it. It MUST
|
||||
seal each continuation's decision (§8) over a payload that commits to the id
|
||||
of the receipt it continues (the first's, or the previous continuation's),
|
||||
so that one piece of work's receipts form a chain within the stream.
|
||||
2. MUST refuse, and seal the refusal of, a later exchange naming a handle it did
|
||||
not see returned to a request it decided. A handle is a bearer string the
|
||||
endpoint minted, and no grant covers it until the enforcement point has bound
|
||||
it to one. A handle it has closed (item 4) or forgotten (a restart, a bound on
|
||||
what it keeps) is refused the same way: fail closed.
|
||||
3. MUST flow-check what the client authored in a later exchange (the answers)
|
||||
as it does the first request's arguments (§4.10), and MUST admit what comes
|
||||
back — status text and the outcome alike — as `data`, labelled as the output
|
||||
of the first request's action and joined with the label of everything the
|
||||
client has sent the work. An exact echo of a handle or state the endpoint
|
||||
minted MAY be left out of the flow check, being the endpoint's own text;
|
||||
anything else the client sends, a handle it made up included, MUST be
|
||||
checked. What the enforcement point forwards SHOULD be built from the fields
|
||||
it decided over, so that nothing it did not check reaches the endpoint.
|
||||
4. MUST meter and debit each later exchange (§5), and, when the outcome is
|
||||
final, MUST seal one **closing record**: a `tool-result` (or `agent-reply`)
|
||||
frame tagged `data`, debiting nothing, whose payload is the content address
|
||||
(§3) of a record naming the first receipt, every continuation's receipt, the
|
||||
joules metered across them, and the outcome's digest. The endpoint works
|
||||
between exchanges, inside no exchange's span, so the record MUST mark that
|
||||
sum `Partial` (§5.2) unless the meter read the work between them.
|
||||
|
||||
The reference gateway (`jcp-gateway`) does this for MCP's `tasks/get`,
|
||||
`tasks/update` and `tasks/cancel`, and for a `tools/call`, `resources/read` or
|
||||
`prompts/get` retried with `inputResponses`; it advertises it in its
|
||||
`server/discover` and `initialize` responses as `continuations`.
|
||||
|
||||
## 7. The decision (REQUIRED)
|
||||
|
||||
Given a Frame, its [SignedGrant](#4-the-grant-required), the caller's DID, a
|
||||
|
|
@ -1212,6 +1259,7 @@ jcp-conformance --bin gen-vectors`).
|
|||
| Runaway loops, no energy accounting | §5 enforced joule budgets, conserved across delegation |
|
||||
| Mutable / optional audit | §8 signed JCR-1 receipts |
|
||||
| Fragmentation across protocols | §6 one frame for tools and agents |
|
||||
| Results fetched later, outside the gate (task handles, interim input requests) | §6.1 continuations, chained to the receipt they continue |
|
||||
|
||||
## 11. Wire binding: `jcp/1` over a byte stream (OPTIONAL)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@
|
|||
//!
|
||||
//! The gateway speaks newline-delimited JSON-RPC with its own client on
|
||||
//! stdin/stdout and with the spawned MCP server over the child's stdio. Every
|
||||
//! `tools/call` is gated, metered, debited, and sealed; receipts stream to
|
||||
//! `JCP_GATEWAY_RECEIPTS` (default `./jcp-gateway-receipts.cose`, length-
|
||||
//! prefixed envelopes) and a one-line summary per call goes to stderr.
|
||||
//! method in `JCP_ENFORCED_METHODS` is gated, metered, debited, and sealed (a
|
||||
//! task's exchanges as continuations of the call that opened it); receipts
|
||||
//! stream to `JCP_GATEWAY_RECEIPTS` (default `./jcp-gateway-receipts.cose`,
|
||||
//! length-prefixed envelopes) and a one-line summary per call goes to stderr.
|
||||
//!
|
||||
//! That file is also read back at startup, because SPEC §8.1 is REQUIRED of
|
||||
//! an enforcement point: it rebuilds its budget state by replaying its own
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue