Skip to content

[Fix] manage_environments tool receives empty arguments on some models - #8

Merged
mrubens merged 1 commit into
developfrom
fix/manage-environments-empty-args-1rofiwhzlacby
Jul 8, 2026
Merged

[Fix] manage_environments tool receives empty arguments on some models#8
mrubens merged 1 commit into
developfrom
fix/manage-environments-empty-args-1rofiwhzlacby

Conversation

@roomote-roomote-v1

Copy link
Copy Markdown

Opened on behalf of Matt Rubens. Follow up by mentioning @openmote, in the web UI, or in Slack.

What changed

The manage_environments MCP tool's definition field used z.union([z.string(), z.record(z.unknown())]) — the only such union in the Roomote MCP server. That schema serializes to a JSON Schema anyOf plus an empty additionalProperties: {} object, which some model/provider tool-call paths drop entirely, sending an empty {} arguments object to the server. The MCP SDK then reports action and definition as undefined and the handler never runs, blocking the environment-setup skill from persisting any environment.

This changes definition to a plain z.string(). The handler in create-environment.ts already accepts YAML/JSON strings and auto-detects format, so no logic change was needed — only the wire schema. The field description now says "YAML or JSON string" instead of "YAML/JSON string or object." A regression test asserts definition is a z.ZodString, not a z.ZodUnion, so the union cannot sneak back in.

Why this change was made

manage_environments was the only Roomote MCP tool that broke on certain model/provider paths, while simple-schema tools (manage_tasks, etc.) worked in the same session. The union schema's anyOf serialization was the differentiator. Removing the union from the wire schema makes the tool arguments survive the tool-call layer reliably regardless of provider.

Impact

Agents calling manage_environments now consistently deliver their action and definition arguments to the server across all models/providers. Object definitions are no longer accepted over the wire (agents pass a YAML or JSON string, which the environment-setup skill already does), while the handler's internal object-handling path remains as a harmless fallback for direct/test callers. No user-visible behavior change beyond the tool working reliably.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Thank you for your contribution! Before we can merge this pull request, we need you to sign our Contributor License Agreement. You can sign it by posting the comment below.


I have read the CLA Document and I hereby sign the CLA


You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

@roomote-roomote-v1

roomote-roomote-v1 Bot commented Jul 8, 2026

Copy link
Copy Markdown
Author

No code issues found. Reviewed the wire-schema change and its regression test. See task

@mrubens
mrubens marked this pull request as ready for review July 8, 2026 20:03
@mrubens
mrubens merged commit 700df5c into develop Jul 8, 2026
1 check passed
@mrubens
mrubens deleted the fix/manage-environments-empty-args-1rofiwhzlacby branch July 8, 2026 20:03
daniel-lxs added a commit that referenced this pull request Jul 10, 2026
Automation scans (e.g. ci-failure-triage on staging) were getting stuck in
long retry loops because some models cannot reliably emit this tool's
nested arguments: the workItems array was sent as a JSON string, fields
were dropped, reasoning text leaked into optional fields, and the act-item
requirements only surfaced as an opaque platform-API 400 after the round
trip. Same failure class as the manage_environments fix (#8): the cure is
a simpler schema, not stricter validation.

- The tool now takes one flat work item per call (scalar params only) and
  is called once per work item; the worker wraps it into the platform
  API's existing workItems array
- executionPrompt, targetRepositoryFullName, and targetEnvironmentId are
  required in the advertised schema, so models see the real contract
  instead of a post-hoc 400
- disposition is retained as an optional enum(['act']) for prompt
  compatibility and hardcoded to act in the handler; workspaceReadiness
  and readinessMessage are removed entirely -- the platform derives
  readiness from targetEnvironmentId and rejects bare_repo for act items,
  so those fields could never be legitimately set (readinessMessage was
  the field that wedged the staging loop)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
daniel-lxs added a commit that referenced this pull request Jul 10, 2026
…116)

Automation scans (e.g. ci-failure-triage on staging) were getting stuck in
long retry loops because some models cannot reliably emit this tool's
nested arguments: the workItems array was sent as a JSON string, fields
were dropped, reasoning text leaked into optional fields, and the act-item
requirements only surfaced as an opaque platform-API 400 after the round
trip. Same failure class as the manage_environments fix (#8): the cure is
a simpler schema, not stricter validation.

- The tool now takes one flat work item per call (scalar params only) and
  is called once per work item; the worker wraps it into the platform
  API's existing workItems array
- executionPrompt, targetRepositoryFullName, and targetEnvironmentId are
  required in the advertised schema, so models see the real contract
  instead of a post-hoc 400
- disposition is retained as an optional enum(['act']) for prompt
  compatibility and hardcoded to act in the handler; workspaceReadiness
  and readinessMessage are removed entirely -- the platform derives
  readiness from targetEnvironmentId and rejects bare_repo for act items,
  so those fields could never be legitimately set (readinessMessage was
  the field that wedged the staging loop)

Co-authored-by: Claude Fable 5 <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.

1 participant