Skip to main content

Harness adapters

An adapter wraps one coding-agent runtime. It implements harness.Harness and returns a harness.Session. harness.Agent is the only consumer of that interface, so a test double is a first-class substitute for a real adapter. Application code usually builds an adapter with its constructor and hands it to harness.NewAgent. See Harness agent.

Harness​

type Harness interface {
SpecificationVersion() string // always "harness-v1"
HarnessID() string
BuiltinTools() map[string]BuiltinTool
DoStart(ctx context.Context, opts StartOptions) (Session, error)
}

harness.SpecificationVersion is the version string. BuiltinTools is keyed by what the runtime reports on tool-call events: the common name when it has one, otherwise the native name.

Optional capabilities are separate interfaces that an adapter may also implement:

InterfacePurpose
harness.BootstrapProviderDeclare a bootstrap recipe.
harness.BuiltinToolApprovalSupportEmit approval requests for built-in tools.
harness.BuiltinToolFilteringSupportHide inactive built-in tools from the runtime.
harness.LifecycleStateValidatorValidate the adapter-defined data in lifecycle state.

StartOptions​

FieldTypeDescription
Headersmap[string]stringHeaders are additional normalized HTTP headers to send with model requests.
SessionIDstringSessionID is the stable identifier for this harness session.
ResumeFrom*ResumeSessionStateResumeFrom is the resume payload from a prior lifecycle method.
ContinueFrom*ContinueTurnStateContinueFrom is the continuation payload from DoSuspendTurn, or nested in ResumeFrom.
PermissionModePermissionModePermissionMode is the approval policy for built-in adapter-native tools.
BuiltinToolFiltering*BuiltinToolFilteringBuiltinToolFiltering lists adapter-native built-in tools available for this session.
Observability*ObservabilityObservability is diagnostics wiring; nil when diagnostics are disabled.
SandboxSessionproviderutils.SandboxSessionSandboxSession is the sandbox the adapter operates against. It is either a NetworkSandboxSession or a caller-provided plain providerutils.SandboxSession (filesystem + process only). Adapters must not stop or destroy the sandbox themselves.
SessionWorkDirstringSessionWorkDir is the absolute path the adapter runs the agent in.

StartOptions.SandboxSession is a harness.NetworkSandboxSession or a plain providerutils.SandboxSession that you supply. An adapter must not stop or destroy the sandbox itself.

Session​

type Session interface {
SessionID() string
IsResume() bool
DoPromptTurn(ctx context.Context, opts PromptTurnOptions) (PromptControl, error)
DoCompact(ctx context.Context, customInstructions string) error
DoContinueTurn(ctx context.Context, opts ContinueTurnOptions) (PromptControl, error)
DoSuspendTurn(ctx context.Context) (*ContinueTurnState, error)
DoDetach(ctx context.Context) (*ResumeSessionState, error)
DoStop(ctx context.Context) (*ResumeSessionState, error)
DoDestroy(ctx context.Context) error
}

An adapter whose runtime cannot compact returns *harness.CapabilityUnsupportedError from DoCompact. A session may also implement harness.HistoryReader (DoReadHistory(ctx, since string) (*ReadHistoryResult, error)). since is a previous result's cursor, which is opaque to the host. An adapter that cannot reach its runtime's store returns *harness.HistoryUnavailableError.

PromptTurnOptions and ContinueTurnOptions​

Both embed harness.TurnSettings, the framework-owned settings captured when a turn begins: Model, Skills, Instructions and Tools.

FieldTypeDescription
(embedded)TurnSettingsEmbedded.
PromptPromptPrompt is the fresh input for this turn.
ResponseFormat*ResponseFormatResponseFormat requested for this turn. Adapters that cannot honor a JSON response format must return a CapabilityUnsupportedError.
EmitEmitFuncEmit is invoked once for each event the adapter produces.
FieldTypeDescription
(embedded)TurnSettingsEmbedded.
ResponseFormat*ResponseFormatResponseFormat of the in-flight turn.
EmitEmitFuncEmit is invoked once for each event the adapter produces.
FieldTypeDescription
Modelstring
Skills[]Skill
Instructionsstring
Tools[]ToolSpec

harness.Prompt is plain text or one user message. Build one with harness.TextPrompt(text).

FieldTypeDescription
Textstring
Message*types.Message

harness.ResponseFormat is the response format for a turn. Type is harness.ResponseFormatText or harness.ResponseFormatJSON. Adapters that cannot produce JSON return *harness.CapabilityUnsupportedError.

FieldTypeDescription
TypeResponseFormatType
Schemamap[string]any
Namestring
Descriptionstring

Skills​

harness.Skill is a self-contained instruction bundle the runtime can load. harness.SkillFile is an extra file, with a skill-relative POSIX Path and its Content. harness.AgentSkill is the consumer-facing alias.

FieldTypeDescription
Namestring
Descriptionstring
Contentstring
Files[]SkillFile

PromptControl​

DoPromptTurn and DoContinueTurn return a harness.PromptControl, the control surface for the turn.

type PromptControl interface {
SubmitToolResult(ctx context.Context, result ToolResultSubmission) error
Done() <-chan struct{} // closed when the turn ends
Err() error // the turn error, after Done is closed
}
FieldTypeDescription
ToolCallIDstring
Outputany
IsErrorbool
ToolResultanyToolResult optionally carries the full tool-result part (TS ToolResultPart) for adapters that forward it verbatim.

A control can also implement:

InterfaceMethod
harness.ToolApprovalSubmitterSubmitToolApproval(ctx, ToolApprovalSubmission) error
harness.UserMessageSubmitterAccepts a user message mid-turn, which is what ExperimentalSteer uses.
harness.CheckpointPinnerPinCheckpoint() (release func()). Pins the replay checkpoint so already-delivered bridge events are kept until you call release.
FieldTypeDescription
ApprovalIDstring
Approvedbool
Reasonstring

Consumer-facing aliases​

The consumer-facing harness.Agent* names are aliases of the specification types, matching the TypeScript HarnessAgent* names.

AliasType
harness.AgentAdapterharness.Harness
harness.AgentAdapterSessionharness.Session
harness.AgentPromptharness.Prompt
harness.AgentPromptControlharness.PromptControl
harness.AgentPromptTurnOptionsharness.PromptTurnOptions
harness.AgentStartOptionsharness.StartOptions

Built-in adapters​

Each adapter is its own package under pkg/harness. Every adapter has a HarnessID and a CredentialEnvironmentVariables list, and most have a bootstrap recipe under a .harness-bootstrap/<id> directory.

PackageConstructorRuntime
harness/claudecodeclaudecode.New(Settings) (*Harness, error)Claude Code. HarnessID is claude-code.
harness/codexcodex.New(Settings) *HarnessOpenAI Codex. HarnessID is codex.
harness/opencodeopencode.CreateOpenCode(...Settings) (harness.Harness, error)OpenCode.
harness/deepagentsdeepagents.CreateDeepAgents(...Settings) harness.HarnessDeep Agents.
harness/cursorcursor.CreateCursor(...Settings) (harness.Harness, error)Cursor, through ACP.
harness/githubcopilotgithubcopilot.CreateGitHubCopilot(...Settings) (harness.Harness, error)GitHub Copilot, through ACP.
harness/grokbuildgrokbuild.CreateGrokBuild(...Settings) (harness.Harness, error)Grok Build, through ACP.
harness/acpacp.CreateACP(Settings) (harness.Harness, error)Any runtime that speaks the Agent Client Protocol. The Cursor, GitHub Copilot and Grok Build adapters are configurations of it.

Claude Code​

claudecode.New starts the Claude Agent SDK in a bridge process inside the sandbox and talks to it over a port the sandbox exposes.

FieldTypeDescription
Authharness.AuthenticationAuth selects the authentication route: unset (auto-detect), "direct", "ai-gateway", or an isolated environment via harness.AuthEnvironment.
CredentialForwardingharness.CredentialForwardingCredentialForwarding customizes each credential value immediately before it is forwarded into the sandbox.
MCPServersmap[string]anyMCPServers are additional MCP server definitions, keyed by name, in the Claude Agent SDK's native configuration format. The name "harness-tools" is reserved.
MaxTurnsintMaxTurns caps how many internal turns the CLI can take before yielding back to the caller. Zero means the CLI's default.
AgentProgressSummariesboolAgentProgressSummaries enables periodic AI-generated progress summaries for running subagents. The summaries are forwarded in raw task_progress stream parts.
ForwardSubagentTextboolForwardSubagentText forwards subagent text and thinking messages in addition to tool activity. Subagent messages are exposed as raw stream parts.
Envmap[string]stringEnv are additional environment variables for the Claude Code process, merged over the resolved authentication environment.
Thinking*ThinkingConfigThinking controls extended-thinking behavior. Defaults to {Type: "adaptive", Display: "summarized"}.
EffortstringEffort controls adaptive-thinking effort: "low", "medium", "high", "xhigh" or "max". Empty uses the Claude Agent SDK default.
PortintPort overrides the port the bridge binds inside the sandbox. Defaults to the first port the sandbox exposes.
PortEndpoint*harness.PortEndpointPortEndpoint overrides the host endpoint used to reach the bridge. Required together with Port for a sandbox that is not a harness.NetworkSandboxSession.
StartupTimeouttime.DurationStartupTimeout bounds how long to wait for the bridge to announce its port. Defaults to 120s.
Reconnectbridge.ReconnectOptionsReconnect tunes reconnection after an established bridge connection drops.
MintBridgeTokenharness.MintBridgeTokenCallbackMintBridgeToken creates the bridge channel token. Defaults to a random 32-byte hex token. Requires the sandbox to expose an ID.
FieldTypeDescription
TypestringType is "adaptive" (default), "enabled" or "disabled".
DisplaystringDisplay is "summarized" (default) or "omitted"; ignored when Type is "disabled".

claudecode.GetBootstrap(ctx) returns the bootstrap recipe. claudecode.BootstrapDir is .harness-bootstrap/claude-code. claudecode.AuthModeDirect and its siblings are the resolved authentication modes.

Codex​

FieldTypeDescription
Authharness.AuthenticationAuth selects the authentication route: unset (auto-detect), "direct", "ai-gateway", or an isolated environment via harness.AuthEnvironment.
CredentialForwardingharness.CredentialForwardingCredentialForwarding customizes each credential value immediately before it is forwarded into the sandbox.
CodexConfigmap[string]anyCodexConfig is additional configuration passed through to Codex as-is (snake_case config.toml keys). Values managed by this adapter take precedence over conflicting entries.
MCPServersmap[string]anyMCPServers are additional MCP server definitions, keyed by name, in Codex's native configuration format.
ReasoningEffortstringReasoningEffort for reasoning-capable models: "low", "medium", "high", "xhigh" or "max". Empty defers to the CLI's default.
WebSearch*boolWebSearch, when true, allows the runtime to use live web search.
PortintPort overrides the port the bridge binds inside the sandbox. Defaults to the first port the sandbox exposes.
PortEndpoint*harness.PortEndpointPortEndpoint overrides the host endpoint used to reach the bridge.
StartupTimeouttime.DurationStartupTimeout bounds how long to wait for the bridge to announce its port. Defaults to 120s.
Reconnectbridge.ReconnectOptionsReconnect tunes reconnection after an established bridge connection drops.
MintBridgeTokenharness.MintBridgeTokenCallbackMintBridgeToken creates the bridge channel token. Defaults to a random 32-byte hex token. Requires the sandbox to expose an ID.

codex.DefaultModel is the model used when none is set. codex.DefaultOpenAIBaseURL is https://api.openai.com/v1.

Authentication​

Every adapter takes an Auth setting of type harness.Authentication. Leave it unset to detect the route, or choose harness.AuthModeDirect, harness.AuthModeAIGateway or an isolated environment with harness.AuthEnvironment. Adapters forward credentials into the sandbox through request transformations where the provider supports it, so the sandbox does not hold the real secret. See Request transformations.