Proposal: make OpenCode harness calls explicit
Summary
I’d like to propose updating the AgentField OpenCode provider to build a
per-run OPENCODE_CONFIG_CONTENT overlay from the existing harness(...)
options. Each opencode run would select a fixed agent with --agent, attach
the system prompt and model to that agent, use steps: 500, apply the supplied
reasoning variant, and run with explicit noninteractive permissions.
This would let OpenCode receive the same intent that the caller already
expressed through the harness API, without changing SWE-AF-specific workflows.
SWE-AF is one consumer of this behavior, but the change should stay generic and
live in the AgentField OpenCode provider.
Problem
The harness already accepts system_prompt, tools, model, variant, cwd,
max_turns, and permission_mode. The OpenCode provider currently uses only a
subset of those values when it builds a command similar to:
opencode run --format json --dir <CWD> -m <MODEL> <PROMPT>
The system prompt is folded into the positional prompt as ordinary text,
tools is not translated into OpenCode permissions, and
permission_mode does not establish a reliable noninteractive boundary. As a
result, a run can depend on ambient OpenCode defaults, use an unintended agent,
duplicate system instructions, or wait for a permission approval that nobody
can provide.
Proposed change
For each standalone OpenCode subprocess, the provider would generate an
OPENCODE_CONFIG_CONTENT overlay with one fixed generic agent name, such as
agentfield-harness. The deployment can continue to own the shared settings
for plugins, providers, model limits, and compaction. Meaning: if you customize your opencode deployment already, this will pickup your global mcp, plugins, etc... and only superceed what is declared.
The generated agent should have this shape:
{
"$schema": "https://opencode.ai/config.json",
"default_agent": "agentfield-harness",
"agent": {
"agentfield-harness": {
"prompt": "<SYSTEM_PROMPT>",
"model": "<MODEL>",
"mode": "primary",
"steps": 500,
"reasoningEffort": "<VARIANT>",
"permission": {
"*": "allow",
"question": "deny",
"task": "deny"
}
}
}
}
reasoningEffort would be omitted when no reasoning variant is supplied. The
AgentField variant and OpenCode reasoningEffort values represent one
logical reasoning-effort setting. When it is supplied, the provider would use
the same value for the agent's reasoningEffort and the OpenCode --variant
command option rather than treating them as independent settings.
At the process boundary, the command would look like this:
OPENCODE_CONFIG_CONTENT=<GENERATED_CONFIG> opencode run --format json --agent agentfield-harness --dir <CWD> -m <MODEL> [--variant <VARIANT>] <PROMPT>
The provider would set OPENCODE_CONFIG_CONTENT in the child process
environment. The SWE-AF caller would continue to pass normal harness options;
it would not need to construct this shell command.
The provider should pass only the task prompt positionally. It should not add a
SYSTEM INSTRUCTIONS: section because the system prompt is now attached to the
OpenCode agent.
Turn and permission semantics
One important distinction is that max_turns must not be mapped to OpenCode
steps. They are different budgets: steps is OpenCode's internal agent
iteration limit and should remain a large, fixed value of 500, while
max_turns remains an AgentField/SWE-AF loop setting.
Map recognized AgentField tools to OpenCode actions as follows:
Read -> read
Write -> edit
Edit -> edit
Glob -> glob
Grep -> grep
Bash -> bash
For the initial integration, I suggest an allow baseline rather than turning
every omitted tool into a deny rule. Explicitly deny only question and task,
so an autonomous run never waits for an approval that cannot be supplied. This
is a compatibility baseline, not yet strict per-role authorization.
That choice is driven by AgentField's current structured-output protocol:
schema-backed runs ask the agent to write .agentfield_output.json, and
OpenCode maps both AgentField Write and Edit to its edit permission. A
strict edit denial would therefore break structured output. Path-limited output
permissions or a different output transport can be considered separately.
Why I think this is useful
- The system prompt becomes an actual OpenCode agent prompt instead of being
repeated in the user-facing request.
--agent and default_agent make the selected agent deterministic.
- The model remains available as an agent default while
-m explicitly selects
the model for a particular run.
- Reasoning effort is represented consistently in the agent configuration and by
the per-run variant option.
- Headless runs can proceed autonomously instead of blocking on permission
prompts.
- Per-run configuration lives in the subprocess environment, so concurrent
runs do not need to share and mutate a temporary config file.
Strategy and scope
I’d keep the first change deliberately narrow:
- Add the OpenCode config-overlay construction to the AgentField OpenCode
provider.
- Preserve the existing model and directory options, adding
--agent and an
optional --variant.
- Make
variant an explicit harness option on SDK surfaces where it is not
already typed, while preserving existing model-variant behavior.
- Keep
max_turns outside the OpenCode configuration.
- Add provider tests for the generated configuration, command construction,
prompt handling, permission defaults, fixed steps: 500, and variant
handling. Maintain Python, Go, and TypeScript parity where those providers
expose the same harness contract.
I would leave opencode serve/--attach, a role/profile registry, per-role MCP
authorization, and a replacement structured-output transport out of the first
patch. Attached sessions load configuration on the server and would need a
separate per-session configuration design.
Acceptance criteria
- A standalone OpenCode run receives the generated
OPENCODE_CONFIG_CONTENT.
- The selected agent, system prompt, model, and permissions are visible in the
effective OpenCode configuration.
steps is always 500 in this overlay; max_turns is never serialized as
steps.
- A supplied reasoning variant is represented as
reasoningEffort in the
agent configuration and as --variant on the command line.
question and task are denied, with no generated ask permissions.
- The positional prompt contains the task only, not a second copy of the
system prompt.
- Existing caller/deployment environment and provider behavior remain
compatible when no OpenCode-specific overrides are supplied.
Feedback requested
Before implementing this, I’d appreciate confirmation that
OPENCODE_CONFIG_CONTENT is the right extension point for per-run OpenCode
configuration, that the fixed agentfield-harness name is acceptable, and that
Python, Go, and TypeScript provider parity is expected for this change. If this
direction looks right, I plan to prepare it as a focused provider-and-tests PR.
note: gpt luna helped me cleanup the proposal and make it (hopefully) more presentable.
Proposal: make OpenCode harness calls explicit
Summary
I’d like to propose updating the AgentField OpenCode provider to build a
per-run
OPENCODE_CONFIG_CONTENToverlay from the existingharness(...)options. Each
opencode runwould select a fixed agent with--agent, attachthe system prompt and model to that agent, use
steps: 500, apply the suppliedreasoning variant, and run with explicit noninteractive permissions.
This would let OpenCode receive the same intent that the caller already
expressed through the harness API, without changing SWE-AF-specific workflows.
SWE-AF is one consumer of this behavior, but the change should stay generic and
live in the AgentField OpenCode provider.
Problem
The harness already accepts
system_prompt,tools,model,variant,cwd,max_turns, andpermission_mode. The OpenCode provider currently uses only asubset of those values when it builds a command similar to:
The system prompt is folded into the positional prompt as ordinary text,
toolsis not translated into OpenCode permissions, andpermission_modedoes not establish a reliable noninteractive boundary. As aresult, a run can depend on ambient OpenCode defaults, use an unintended agent,
duplicate system instructions, or wait for a permission approval that nobody
can provide.
Proposed change
For each standalone OpenCode subprocess, the provider would generate an
OPENCODE_CONFIG_CONTENToverlay with one fixed generic agent name, such asagentfield-harness. The deployment can continue to own the shared settingsfor plugins, providers, model limits, and compaction. Meaning: if you customize your opencode deployment already, this will pickup your global mcp, plugins, etc... and only superceed what is declared.
The generated agent should have this shape:
{ "$schema": "https://opencode.ai/config.json", "default_agent": "agentfield-harness", "agent": { "agentfield-harness": { "prompt": "<SYSTEM_PROMPT>", "model": "<MODEL>", "mode": "primary", "steps": 500, "reasoningEffort": "<VARIANT>", "permission": { "*": "allow", "question": "deny", "task": "deny" } } } }reasoningEffortwould be omitted when no reasoning variant is supplied. TheAgentField
variantand OpenCodereasoningEffortvalues represent onelogical reasoning-effort setting. When it is supplied, the provider would use
the same value for the agent's
reasoningEffortand the OpenCode--variantcommand option rather than treating them as independent settings.
At the process boundary, the command would look like this:
The provider would set
OPENCODE_CONFIG_CONTENTin the child processenvironment. The SWE-AF caller would continue to pass normal harness options;
it would not need to construct this shell command.
The provider should pass only the task prompt positionally. It should not add a
SYSTEM INSTRUCTIONS:section because the system prompt is now attached to theOpenCode agent.
Turn and permission semantics
One important distinction is that
max_turnsmust not be mapped to OpenCodesteps. They are different budgets:stepsis OpenCode's internal agentiteration limit and should remain a large, fixed value of
500, whilemax_turnsremains an AgentField/SWE-AF loop setting.Map recognized AgentField tools to OpenCode actions as follows:
For the initial integration, I suggest an allow baseline rather than turning
every omitted tool into a deny rule. Explicitly deny only
questionandtask,so an autonomous run never waits for an approval that cannot be supplied. This
is a compatibility baseline, not yet strict per-role authorization.
That choice is driven by AgentField's current structured-output protocol:
schema-backed runs ask the agent to write
.agentfield_output.json, andOpenCode maps both AgentField
WriteandEditto itseditpermission. Astrict edit denial would therefore break structured output. Path-limited output
permissions or a different output transport can be considered separately.
Why I think this is useful
repeated in the user-facing request.
--agentanddefault_agentmake the selected agent deterministic.-mexplicitly selectsthe model for a particular run.
the per-run variant option.
prompts.
runs do not need to share and mutate a temporary config file.
Strategy and scope
I’d keep the first change deliberately narrow:
provider.
--agentand anoptional
--variant.variantan explicit harness option on SDK surfaces where it is notalready typed, while preserving existing model-variant behavior.
max_turnsoutside the OpenCode configuration.prompt handling, permission defaults, fixed
steps: 500, and varianthandling. Maintain Python, Go, and TypeScript parity where those providers
expose the same harness contract.
I would leave
opencode serve/--attach, a role/profile registry, per-role MCPauthorization, and a replacement structured-output transport out of the first
patch. Attached sessions load configuration on the server and would need a
separate per-session configuration design.
Acceptance criteria
OPENCODE_CONFIG_CONTENT.effective OpenCode configuration.
stepsis always500in this overlay;max_turnsis never serialized assteps.reasoningEffortin theagent configuration and as
--varianton the command line.questionandtaskare denied, with no generatedaskpermissions.system prompt.
compatible when no OpenCode-specific overrides are supplied.
Feedback requested
Before implementing this, I’d appreciate confirmation that
OPENCODE_CONFIG_CONTENTis the right extension point for per-run OpenCodeconfiguration, that the fixed
agentfield-harnessname is acceptable, and thatPython, Go, and TypeScript provider parity is expected for this change. If this
direction looks right, I plan to prepare it as a focused provider-and-tests PR.
note: gpt luna helped me cleanup the proposal and make it (hopefully) more presentable.