Skip to content

feat: allow read-only shares to read A2A tasks#2191

Draft
QuentinBisson wants to merge 1 commit into
kagent-dev:mainfrom
QuentinBisson:feat/a2a-readonly-share-reads
Draft

feat: allow read-only shares to read A2A tasks#2191
QuentinBisson wants to merge 1 commit into
kagent-dev:mainfrom
QuentinBisson:feat/a2a-readonly-share-reads

Conversation

@QuentinBisson

Copy link
Copy Markdown
Contributor

What

Read-only share tokens can now read tasks over A2A (ListTasks, GetTask). They were blocked from every A2A method because shareTokenMiddleware rejects all non-GET requests on the A2A path, and A2A is JSON-RPC over POST. Read-only is the default share mode (session_shares.go defaults read_only to true), so the share-scoped task read path added in #2187 was unreachable for the common case.

How

Read-only enforcement for A2A moves from the transport verb to the request handler:

  • Reads pass through: ListTasks, GetTask, push-config get/list, SubscribeToTask.
  • Mutating methods are rejected under a read-only share via requireWritableShare: SendMessage, SendStreamingMessage, CancelTask, CreateTaskPushConfig, DeleteTaskPushConfig.
  • The session REST path keeps its existing verb-based read-only block.

The middleware no longer blanket-blocks non-GET A2A requests for read-only shares, so the per-method guards are what stop a read-only share from mutating a session. Guarding at the handler covers both wires (v0 and v1 route the same methods to it).

Behavior change

A read-only share attempting a mutating A2A method now returns a JSON-RPC error result instead of an HTTP 403.

Follows #2187 (store-backed ListTasks); branched from main, no code dependency on it.

Read-only share tokens were blocked from every A2A method because the
share middleware rejects all non-GET requests on the A2A path, and A2A
is JSON-RPC over POST. That left ListTasks and GetTask unreachable for a
read-only share, which is the default share mode.

Move read-only enforcement for A2A off the transport verb and into the
request handler: reads (ListTasks, GetTask, push-config gets,
SubscribeToTask) pass through, and mutating methods (SendMessage,
SendStreamingMessage, CancelTask, CreateTaskPushConfig,
DeleteTaskPushConfig) are rejected via requireWritableShare. The session
REST path keeps its verb-based read-only block.

Read-only writes over A2A now return a JSON-RPC error instead of HTTP 403.

Signed-off-by: QuentinBisson <quentin@giantswarm.io>
@EItanya

EItanya commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

@onematchfox would love your thoughts as well

@github-actions github-actions Bot added the enhancement New feature or request label Jul 9, 2026
@onematchfox

Copy link
Copy Markdown
Contributor

@onematchfox would love your thoughts as well

I'm on PTO at the moment so haven't looked at the code/implementation itself but the general ask/fix makes sense to me. My original implementation focussed on the controller API endpoints used to read state from the Kagent DB rather than the semantics of similar functionality that could be achieved directly via A2A methods.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants