Summary
no-mistakes sends structured output (json_schema) to OpenCode at the message body root, but OpenCode >= 1.17.x expects it nested inside info.format. This breaks the review, document, and agent-driven test steps — all three fail with "opencode returned no text output".
This is a more specific root cause for #277 — the "schema rejection" errors in the daemon logs show exactly where the format is misplaced.
Environment
no-mistakes version v1.30.1 (59dfa25) 2026-06-21T22:28:43Z
OpenCode 1.17.9
macOS arm64
Reproduction
1. Configure no-mistakes to use OpenCode
# ~/.no-mistakes/config.yaml
agent: opencode
2. Push a branch through the gate
git push no-mistakes feat/test-opencode-review
no-mistakes axi run --intent "test opencode review" --yes
3. Observe the failure
step review failed: agent review: opencode returned no text output
4. Check daemon logs
~/.no-mistakes/logs/daemon.log
Shows repeated schema rejections:
WARN schema rejection kind=Body reason="Expected OutputFormatJsonSchema, got
{\"type\":\"json_schema\",\"schema\":{...},\"retryCount\":1}
at [0][\"info\"][\"format\"]"
The at [0]["info"]["format"] path tells us exactly where OpenCode expects the format.
Root Cause Location
internal/agent/opencode_http.go:sendMessage() — around line 84:
// CURRENT (broken) — format at message body root:
if len(schema) > 0 {
body["format"] = map[string]any{
"type": "json_schema",
"schema": json.RawMessage(schema),
"retryCount": 1,
}
}
OpenCode 1.17.x expects format nested under info:
{
"role": "user",
"parts": [{"type": "text", "text": "..."}],
"info": {
"format": {
"type": "json_schema",
"schema": {...}
}
}
}
Verification (API-level proof)
Testing against opencode serve directly:
- Root-level format → rejected:
"Expected OutputFormatJsonSchema"
- Nested in info.format → accepted:
200 OK, streaming response with structured output
Proposed Fix
// FIX — nest format inside info:
if len(schema) > 0 {
info := map[string]any{
"format": map[string]any{
"type": "json_schema",
"schema": json.RawMessage(schema),
},
}
body["info"] = info
}
Bonus: The info object also accepts "model" for per-message model selection:
info["model"] = "github-copilot/claude-sonnet-4.6"
This would allow the review/document/test agents to use a specific model without changing the global OpenCode config.
Use Case Context
We deploy no-mistakes in a Go 1.26 microservice platform (~200K LOC). Our org disabled Claude Code subscriptions, so we can only use opencode as the agent. All agent-driven steps (review, document, test evidence) fail because of this format nesting issue.
Impact: Cannot use the review step at all with OpenCode. Forced to --skip=review,document on every run — every PR goes through without AI code review.
Related
Summary
no-mistakessends structured output (json_schema) to OpenCode at the message body root, but OpenCode >= 1.17.x expects it nested insideinfo.format. This breaks the review, document, and agent-driven test steps — all three fail with"opencode returned no text output".This is a more specific root cause for #277 — the "schema rejection" errors in the daemon logs show exactly where the format is misplaced.
Environment
Reproduction
1. Configure no-mistakes to use OpenCode
2. Push a branch through the gate
git push no-mistakes feat/test-opencode-review no-mistakes axi run --intent "test opencode review" --yes3. Observe the failure
4. Check daemon logs
Shows repeated schema rejections:
The
at [0]["info"]["format"]path tells us exactly where OpenCode expects the format.Root Cause Location
internal/agent/opencode_http.go:sendMessage()— around line 84:OpenCode 1.17.x expects format nested under
info:{ "role": "user", "parts": [{"type": "text", "text": "..."}], "info": { "format": { "type": "json_schema", "schema": {...} } } }Verification (API-level proof)
Testing against
opencode servedirectly:"Expected OutputFormatJsonSchema"200 OK, streaming response with structured outputProposed Fix
Bonus: The
infoobject also accepts"model"for per-message model selection:This would allow the review/document/test agents to use a specific model without changing the global OpenCode config.
Use Case Context
We deploy
no-mistakesin a Go 1.26 microservice platform (~200K LOC). Our org disabled Claude Code subscriptions, so we can only useopencodeas the agent. All agent-driven steps (review, document, test evidence) fail because of this format nesting issue.Impact: Cannot use the review step at all with OpenCode. Forced to
--skip=review,documenton every run — every PR goes through without AI code review.Related
set -- --gate "$(pwd)"can resolve to ".", daemon rejects with "invalid gate path: ." #269 — post-receive hook gate path resolves to.— worktree compatibility