Skip to content

fix(adk): re-send task_id/agent_id in state updates for backend compatibility#405

Merged
max-parke-scale merged 1 commit into
nextfrom
maxparke/fix-state-update-backend-compat
Jun 17, 2026
Merged

fix(adk): re-send task_id/agent_id in state updates for backend compatibility#405
max-parke-scale merged 1 commit into
nextfrom
maxparke/fix-state-update-backend-compat

Conversation

@max-parke-scale

@max-parke-scale max-parke-scale commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

What

StateService.update_state re-sends task_id/agent_id in the states.update request body (via extra_body).

Why

0.13.0's Stainless-generated client dropped task_id/agent_id from states.update(), and the ADK stopped sending them. Backends predating scale-agentex#278 still require those fields, so every state write returned 422 Field required. On the Cengage agent (centipede-student-assistant-agentex-agent) this dropped multi-turn context on every turn — ~22k failures over ~21h, logged at warn level so nothing alerted.

Backends post-#278 accept-and-ignore the fields, so re-sending is compatible with both old and new servers — it closes the version-skew window where the client outran the backend rollout reaching the customer (2.10.0-rc).

Test

tests/lib/adk/test_state_service.py asserts update_state forwards task_id/agent_id in the request body — KeyErrors without the fix. ruff check, pyright, and the test pass locally.

Notes

Issue #1 of 3 from the 0.13.0 incident; ships in the 0.13.1 hotfix. The namespace-version guard (issue #2) is a separate PR; the APM route-doubling (issue #3) is under investigation.

🧑‍💻🤖 — posted via Claude Code

Greptile Summary

  • Restores ADK state update compatibility by sending task_id and agent_id in the states.update request body via extra_body.
  • Keeps the generated state parameter while adding the legacy identifiers required by older backends.
  • Adds regression coverage for forwarding the parent identifiers during StateService.update_state.

Confidence Score: 5/5

The change is narrowly scoped to restoring compatibility for ADK state updates and includes targeted regression coverage.

No correctness issues were identified in the changed service logic or test coverage, and the update preserves the generated state payload while adding the legacy identifiers expected by older backends.

T-Rex T-Rex Logs

What T-Rex did

  • Observed the pre-change state-update test output, which exited with code 0 and showed mocked states.update kwargs without extra_body.
  • Observed the post-change state-update test output, which exited with code 0 and showed mocked states.update kwargs now including extra_body with {'agent_id': 'a1', 'task_id': 't1'}, while state_id and state remained unchanged (state_id: 's1', state: {'k': 'v'}).
  • Reviewed the regression-test attempt log, which documented the command and import blocker and did not contradict the direct head behavior shown by the before/after results.

View all artifacts

T-Rex Ran code and verified through T-Rex

Reviews (1): Last reviewed commit: "fix(adk): re-send task_id/agent_id in st..." | Re-trigger Greptile

0.13.0's generated client dropped task_id/agent_id from states.update(),
and the ADK stopped sending them in the body. Backends predating
scale-agentex#278 still require those fields, so every state write 422'd
("Field required") — multi-turn context was lost on every turn (SEV,
~22k failures over ~21h on the Cengage agent).

Re-send both via extra_body. Backends post-#278 accept-and-ignore them,
so this is compatible with old and new servers. Adds a regression test
asserting StateService.update_state forwards them in the request body.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@max-parke-scale max-parke-scale merged commit f59f26d into next Jun 17, 2026
42 checks passed
@max-parke-scale max-parke-scale deleted the maxparke/fix-state-update-backend-compat branch June 17, 2026 16:41
@stainless-app stainless-app Bot mentioned this pull request Jun 17, 2026
max-parke-scale added a commit that referenced this pull request Jun 17, 2026
Generalizes the #405 regression guard. Captures the requests the ADK emits
(states.create/update for v1) and validates each against a window of supported
server OpenAPI contracts vendored under tests/compat/server_specs/: `current`
(scale-agentex main) and `min-supported` (pre-#278, which still requires
task_id/agent_id in the state body).

Catches the 0.13.0 class of break — a client that drops a field an older
deployed server still requires. Verified: with the field-drop, states.update
fails "task_id/agent_id required" against min-supported while passing current.

Specs are vendored for deterministic CI (no network); refresh_specs.py re-pulls
them at the SHAs in manifest.json. Advance min-supported as the oldest deployed
server moves forward; extend _OPERATIONS for more ADK operations.

Stacked on #405 (needs the extra_body fix so states.update passes).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants