Repository navigation
bug(api): POST /api/agent/execute_command cannot be called by any client — Form and dict body cannot both be satisfied #15527
Description
Activity
- addedbugSomething isn't workingSomething isn't workingarea: api-contractWave 2 · cluster C — Frontend↔backend API contractWave 2 · cluster C — Frontend↔backend API contract
on Sep 2, 2026 Delivered in PR #15541.
Refs, notCloses— three of four acceptance criteria are met and
the fourth cannot be done fromDev_new_gui.AC State Evidence Accepts a body a client can construct — one request model, not dict+Formmet api/schemas_agent_requests.py::CommandExecutePayload;execute_command(request, payload, admin_check)inapi/agent.py. Measured:before: media=['application/x-www-form-urlencoded']/after: media=['application/json'], andPOST json {"command": "ls", "session_id": "s1"}moves from422 missing body.command_datato200.admin_checkanduser_rolesemantics unchangedmet admin_check: bool = Depends(check_admin_permission)untouched.user_roleis a model field with the same"user"default: absent ->200 {"user_role":"user"}, supplied ->200 {"user_role":"admin"}.send_commandsends that body; its_UNSATISFIABLEentry is removed fromrepo_tests/sdk_request_body_test.pyhalf met The SDK now posts {"command": command}and dropssession_id, which named nothing the route has.repo_tests/sdk_request_body_test.pydoes not exist onDev_new_gui— it is on the unmerged PR #15526, and the entry is checked to still be necessary, so it must come out when that PR rebases onto #15541. Flagged there.The same fix reaches libs/autobot-sdk-ts'ssendCommandmet sendCommand(command)posts{ command }.Also added, for the class rather than the instance:
repo_tests/route_form_and_json_body_are_not_mixed_test.py. It sweeps 2791 route handlers
across both backends andautobot_shared, of which 24 declare aFormfield, and asserts
none of those also declares a JSON body parameter. This route was the only violation on the
tree; it is now zero. Three mutations are recorded on the PR, including one that misspells
theFormtoken and proves the sweep is matching a token the source actually emits.Close this once #15526 lands with the
_UNSATISFIABLEentry removed.- added a commit that references this issue
on Sep 12, 2026 Closure check against
origin/main(360e08e). All 4 ACs verified independently, not assumed from the earlier comment.AC Status Evidence One request model, no dict+FormmixMet autobot-backend/api/agent.py:845-847—execute_command(request, payload: CommandExecutePayload, admin_check).CommandExecutePayload(api/schemas_agent_requests.py:60-64):command: str,user_role: str = "user".admin_check/user_rolesemantics unchangedMet admin_check: bool = Depends(check_admin_permission)untouched;user_rolekeeps its"user"default, read atagent.py:871aspayload.user_role.send_commandsends that body;_UNSATISFIABLEentry removedMet libs/autobot-sdk-python/autobot_sdk/resources/agents.py:50-59posts{"command": command}, dropssession_id.repo_tests/sdk_request_body_test.py— grepped directly, no_UNSATISFIABLEstring present.TS SDK's sendCommandgets the same fixMet libs/autobot-sdk-ts/src/resources/agents.ts:48—sendCommand(command: string).Delivered across #15526 (recorded then removed the unsatisfiable test entry) and #15541 (the actual route/SDK fix, merged 2026-09-03). Both merged; the earlier comment's "cannot be done from Dev_new_gui" was a same-day sequencing note (PR #15526 landed hours after that comment), not a rename issue — confirmed by reading the merge timestamps directly.
Closing.
What
POST /api/agent/execute_command(autobot-backend/api/agent.py:836) cannot be calledsuccessfully by any client. Its signature is:
The
Formdefault makes FastAPI read the whole body as form data, and a form fieldarrives as a string, so
command_data: dictcan never validate. FastAPI publishes theoperation as
application/x-www-form-urlencodedwithcommand_datarequired — acombination nothing can satisfy.
Measured
Mounted through the router registry with
check_admin_permissionoverridden so body parsingis what is observed, every candidate shape answers 422:
Why it matters
autobot_sdk.resources.agents.send_commandand the TypeScript SDK'ssendCommandbothtarget this route. Neither can be corrected client-side, because there is no correct body.
PR #15526 therefore records the row as unsatisfiable in
repo_tests/sdk_request_body_test.pyrather than inventing a body — and that entry ischecked to still be necessary, so fixing this route makes that guard fail and the entry
comes out with it.
Acceptance criteria
POST /api/agent/execute_commandaccepts a body a client can construct — one requestmodel rather than a
dictbody parameter mixed with aFormfieldadmin_checkanduser_rolesemantics are unchanged (this is a parsing fix, not anauthorization change)
autobot_sdk.resources.agents.send_commandsends that body, and its_UNSATISFIABLEentry is removed fromrepo_tests/sdk_request_body_test.pylibs/autobot-sdk-ts'ssendCommandFound while delivering #15057. Refs #15057, #15526.