Skip to content

[BUG] Exact A2A GetTask cannot retrieve controller-persisted tasks #2464

Closed

Description

@erauner12

Scope clarification

This issue now tracks exact A2A GetTask retrieval of controller-persisted tasks.

The separately reproduced runtime identity defect affecting persisted continuation is tracked in:

  • #2465 — runtime task-store callbacks lose authenticated user context before task resolution.

A separately suspected controller-hop defect was tracked in #2467, but it was not independently reproduced and is now closed.

The original reproduction evidence below is retained because it exposed the exact-read defect tracked here and the runtime identity defect in #2465.

📋 Prerequisites

  • I have searched the existing issues to avoid creating a duplicate
  • By submitting this issue, you agree to follow our Code of Conduct
  • I am using the latest version of the software
  • I have tried to clear cache/cookies or used incognito mode (if ui-related)
  • I can consistently reproduce this issue

🎯 Affected Service(s)

Controller Service

🚦 Impact/Severity

Blocker

🐛 Bug Description

Tasks created and persisted through the kagent controller A2A endpoint are
visible through store-backed ListTasks and through an authenticated REST
GET /api/tasks/{id}, but they cannot be resolved through exact A2A
GetTask or used to resume a persisted input-required task.

The failure is independent of the A2A wire version. It reproduced across all
four create/resume combinations:

  • A2A 0.3 → A2A 0.3
  • A2A 0.3 → A2A 1.0
  • A2A 1.0 → A2A 0.3
  • A2A 1.0 → A2A 1.0

The apparent cause is an ownership/identity mismatch. The controller persists
the task under the authenticated initiating principal, while the runtime later
performs its REST task lookup using the runtime service account. Because task
access is owner-scoped, that lookup reports that the existing task was not
found.

This prevents A2A clients from safely resuming controller-routed human-in-the-loop
interactions. Re-sending the original request is not a safe workaround because
it creates a new task and could duplicate an already accepted action.

Scope clarification

The defects are now tracked separately:

This issue should remain open while the applicable legacy-path fix and regression
coverage are evaluated.

🔄 Steps To Reproduce

  1. Deploy kagent v0.10.0-rc1 with controller task persistence and authenticated,
    owner-scoped task access enabled.

  2. Through the controller A2A endpoint, send a message to an agent that produces
    an input-required task. Retain the returned taskId and contextId.

  3. From a fresh client process authenticated as the same initiating principal:

    • Call ListTasks/tasks/list with the retained contextId.
    • Confirm that the expected task is returned in input-required.
    • Call GetTask/tasks/get with the exact retained taskId.
  4. Observe that exact GetTask returns JSON-RPC error -32001 task_not_found,
    despite ListTasks returning the task.

  5. Send a resume message containing the same taskId and contextId.

  6. Observe that resume fails. Controller logs show the runtime attempting
    GET /api/tasks/<taskId> and receiving Task not found.

  7. Repeat with the four create/resume wire combinations:
    0.3→0.3, 0.3→1.0, 1.0→0.3, and 1.0→1.0.
    All combinations reproduce the failure.

🤔 Expected Behavior

An exact A2A GetTask request should retrieve a controller-persisted task when
the caller is authorized to access it.

A resume message containing the original taskId and contextId should resolve
that persisted input-required task and continue the same interaction,
regardless of whether the compatible 0.3 or 1.0 wire is used.

📱 Actual Behavior

Store-backed ListTasks returns the expected task, but exact A2A GetTask returns:

-32001 task_not_found

Attempting to resume the same task also fails. The controller logs show the
runtime performing:

GET /api/tasks/<redacted-task-id> → Task not found

Database inspection confirms that the task exists. An authenticated REST
request made as the initiating principal can retrieve it.

The observed ownership differs between controller-created and direct-runtime
tasks:

  • Controller-created task: owned by the initiating controller-route principal
  • Runtime lookup: authenticated as the agent runtime service account

This causes the owner-scoped lookup to return not found.

💻 Environment

  • OS and version: macOS, client workstation
  • Kubernetes version/provider: Internal environment; available privately if needed
  • Browser: Not applicable
  • Application version: kagent v0.10.0-rc1
  • Deployment mode: Helm/Kubernetes
  • Authentication mode: trusted-proxy / service-account authentication
  • Task persistence: PostgreSQL-backed controller task store
  • A2A versions tested: 0.3 and 1.0

🔧 CLI Bug Report

Not attached because the reproduction occurred in an internal Kubernetes
environment and the generated report may contain internal infrastructure or
authentication details.

The issue includes sanitized, deterministic reproduction evidence. I can
provide a reviewed and redacted bug report privately if maintainers need
additional diagnostics.

🔍 Additional Context

The store-backed task-query wrapper currently appears to override only
ListTasks. Exact GetTask, CancelTask, and SubscribeToTask continue
through the passthrough/runtime path.

The observed behavior also appears to contradict these existing source comments:

  • a2av0_tasks_list.go:
    “tasks/get is left to the underlying v0 handler, which already routes it to
    the store-backed GetTask”

  • task_query_store.go:
    “GetTask, which already resolves to the same store via the passthrough”

The legacy package remains in current main source, but the supported
current-main controller-v2 uses a different gateway path. Source presence alone
is therefore not runtime evidence for current main.

The current controller-v2/runtime identity-lifecycle defect is tracked
separately in #2465.

For the legacy controller path tracked here, serve exact GetTask requests directly
from the controller's authoritative, owner-scoped persistent task store without
delegating to the runtime. Persisted resume additionally depends on the
authenticated request-identity contract tracked in #2465.

Focused regression-test expectations for this issue:

  • Verify owner isolation, persistent hits, no delegation for absent identity or
    caller-scoped not-found, non-not-found error propagation, requested history
    shaping, artifact retention, and non-mutation of stored tasks.
  • For any maintained release that ships the legacy path, cover persisted exact
    GetTask and HITL resume on both supported wires, including the four cross-wire
    resume combinations.

Temporary client-side mitigation exists only for reads: a client can perform an
exact-ID match through ListTasks after GetTask returns -32001. There is no safe
equivalent for resume because replaying the message could duplicate an accepted
operation.

I can help validate a proposed fix against the dual-wire GetTask and four-way
HITL resume matrix.

Related current-main source:

Reproduction matrix

Created with Read/resumed with ListTasks GetTask Resume
0.3 0.3 task found -32001 failed
0.3 1.0 task found -32001 failed
1.0 0.3 task found -32001 failed
1.0 1.0 task found -32001 failed

📋 Logs

A2A GetTask:
JSON-RPC error: code=-32001, class=task_not_found

Controller/runtime lookup:
GET /api/tasks/<redacted-task-id> → Task not found

Persistence verification:
ListTasks(contextId=<redacted>) → exact task found, state=input-required
REST GET /api/tasks/<redacted-task-id> as initiating principal → task found

📷 Screenshots

No response

🙋 Are you willing to contribute?

  • I am willing to submit a PR to fix this issue

Activity

  1. added theissue type on Aug 17, 2026
  2. erauner12 commented on Aug 17, 2026

    @erauner12
    ContributorAuthor

    Implementation draft for the legacy controller exact-task-read scope: erauner12/kagent#12

    The current controller-v2/runtime identity-lifecycle defect is tracked separately in #2465, where its implementation draft is linked. No live validation is claimed by this comment.

  3. erauner12 commented on Aug 18, 2026

    @erauner12
    ContributorAuthor

    Sanitized follow-up from validation with an independent external A2A client: this behavior separates into three distinct seams.

    1. Persistent exact reads: erauner12/kagent#12 serves owner-scoped exact GetTask from the controller store. Exact GetTask succeeded directly on both A2A 0.3 and 1.0, with zero ListTasks compatibility fallbacks.
    2. Legacy controller outbound identity: erauner12/kagent#13 is the focused two-file change that forwards the trusted effective user from the legacy controller to the managed runtime, using the authenticated principal or validated share owner.
    3. Go runtime returned-context identity: erauner12/kagent#11 is Go-runtime-only and is associated with #2465. It is neither the persistent exact-read fix nor proof of the legacy controller outbound seam.

    The same pre-fix validation still saw persisted input-required resume through a Python declarative runtime fail: the owner-bound callback lookup returned Task not found. This isolates the legacy outbound identity seam after exact reads are working; it does not claim post-fix resume success.

  4. changed the title [-][BUG] Controller-persisted A2A tasks cannot be retrieved or resumed through the runtime[/-] [+][BUG] Exact A2A GetTask cannot retrieve controller-persisted tasks[/+] on Aug 18, 2026
  5. erauner12 commented on Aug 18, 2026

    @erauner12
    ContributorAuthor

    Draft fix: #2484 targets release/v0.10.x and serves exact owner-scoped GetTask reads from the persistent controller store, while preserving caller-scoped authorization and delegate-on-miss behavior.

  6. added a commit that references this issue on Aug 22, 2026
    03e950f
  7. EItanya commented on Oct 16, 2026

    @EItanya
    Contributor

    Fixed on release/v0.10.x by #2484. Exact GetTask now reads directly from the controller's authoritative task store, scoped to the caller, and applies the requested history length. A missing task no longer falls through to the runtime.

    The related continuation identity fixes in #2483 and #2507 are also merged into that branch. Closing this as resolved. Thanks for the detailed report!

    🤖 AI-assisted triage.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions