Documentation
¶
Overview ¶
Package bmaexecutor implements the BMA Executor Protocol (bma.executor.v1.1, generated from contracts/bma): the executor end (Client: token bootstrap, pluggable transport, JSON-RPC 2.0, registration, heartbeat, reconnect with resume, dispatch, tool cancellation, retried results, artifacts, MCP channel), the execution Core with registrable capabilities (process.*, skill.install, ...), and the harness end (Harness).
Index ¶
- Constants
- Variables
- func ApprovalID(sessionID, turnID, callID string) string
- func CloseCode(err error) int
- func NamedPipeListener(name string) (net.Listener, error)
- func NewParams(method string) any
- func NewResult(method string) any
- func NewToolInput(input ToolInput) json.RawMessage
- func Pipe(protocol string) (executor Conn, harness Conn)
- func RequestID(ctx context.Context) string
- func SendExecutorCapabilitiesUpdate(ctx context.Context, rpc RPC, params ExecutorCapabilitiesUpdateParams) error
- func SendExecutorClose(ctx context.Context, rpc RPC, params ExecutorCloseParams) error
- func SendProcessStatus(ctx context.Context, rpc RPC, params ProcessStatusParams) error
- func SendSessionEventDelta(ctx context.Context, rpc RPC, params SessionEventDeltaParams) error
- func SendSessionStatus(ctx context.Context, rpc RPC, params SessionStatusParams) error
- func SendToolProgress(ctx context.Context, rpc RPC, params ToolProgressParams) error
- func StaticToken(wsURL, token string) func(context.Context) (ExecutorTokenResponse, error)
- type ACPAgent
- func (a *ACPAgent) Capability() AgentCapability
- func (a *ACPAgent) Close() error
- func (a *ACPAgent) CloseSession(ctx context.Context, sessionID, _ string) error
- func (a *ACPAgent) MaxResidentSessions() int
- func (a *ACPAgent) OpenTurn(ctx context.Context, params TurnStartParams) (TurnStartResult, error)
- func (a *ACPAgent) RunTurn(ctx context.Context, turn *AgentTurn) error
- func (a *ACPAgent) SuspendSession(ctx context.Context, sessionID string) error
- func (a *ACPAgent) WaitPrewarm(ctx context.Context) error
- type ACPAgentOptions
- type ACPInputFile
- type ACPInputFiles
- type ACPInteractionEvent
- type ACPModelUpstream
- type Ack
- func SendInteractionCancel(ctx context.Context, rpc RPC, params InteractionCancelParams) (Ack, error)
- func SendSessionEnded(ctx context.Context, rpc RPC, params SessionEndedParams) (Ack, error)
- func SendSessionReady(ctx context.Context, rpc RPC, params SessionReadyParams) (Ack, error)
- func SendToolResult(ctx context.Context, rpc RPC, params ToolResultParams) (Ack, error)
- type AgentCapability
- type AgentCustomToolResultParams
- type AgentCustomToolUseEvent
- type AgentError
- type AgentErrorInfo
- type AgentEventRecord
- type AgentHandler
- type AgentHarnessCapability
- type AgentInputBlock
- type AgentMCPToolResultEvent
- type AgentMCPToolUseEvent
- type AgentMessageEvent
- type AgentModel
- type AgentModelTokens
- type AgentPlatform
- type AgentSessionSuspender
- type AgentThinkingEvent
- type AgentToolResultEvent
- type AgentToolUseEvent
- type AgentTurn
- func (t *AgentTurn) ApprovalID(callID string) string
- func (t *AgentTurn) CancelInteraction(interactionID, reason string)
- func (t *AgentTurn) Delta(eventID, eventType string, index int64, text string)
- func (t *AgentTurn) Emit(event any) (string, error)
- func (t *AgentTurn) EmitWithID(eventID string, event any) (string, error)
- func (t *AgentTurn) EnvironmentInfo() *EnvironmentInfo
- func (t *AgentTurn) Flush(ctx context.Context) error
- func (t *AgentTurn) Inputs() <-chan TurnInputParams
- func (t *AgentTurn) NewEventID() string
- func (t *AgentTurn) Params() TurnStartParams
- func (t *AgentTurn) RefreshModelToken(ctx context.Context) (ModelTokenRefreshResult, error)
- func (t *AgentTurn) RefreshToolsToken(ctx context.Context) (ToolsTokenRefreshResult, error)
- func (t *AgentTurn) RequestCustomTool(ctx context.Context, name string, input map[string]any) (string, AgentCustomToolResultParams, error)
- func (t *AgentTurn) RequestInteraction(ctx context.Context, params InteractionRequestParams) (InteractionResponseParams, error)
- func (t *AgentTurn) SessionID() string
- func (t *AgentTurn) Tools() ToolRoute
- func (t *AgentTurn) TurnID() string
- type AgentTurnConfig
- type ArtifactCapability
- type ArtifactRef
- type BashInput
- type BashResult
- type CallMethod
- type CallToolOptions
- type Capabilities
- type Capability
- type ChannelTarget
- type Client
- func (c *Client) ActiveSessions() []string
- func (c *Client) ConnectionID() string
- func (c *Client) Done() <-chan struct{}
- func (c *Client) Err() error
- func (c *Client) ExecutorID() string
- func (c *Client) OnDrain(handler DrainHandler)
- func (c *Client) OnSessionAssign(handler SessionAssignHandler)
- func (c *Client) OnSessionStop(handler SessionStopHandler)
- func (c *Client) OnToolCallAccept(accept func(ToolCallParams) error)
- func (c *Client) OpenMCPChannel(ctx context.Context, sessionID, serverKey string) (*MCPChannel, error)
- func (c *Client) RefreshModelToken(ctx context.Context, sessionID, turnID string) (ModelTokenRefreshResult, error)
- func (c *Client) RefreshToolsToken(ctx context.Context, sessionID, turnID string) (ToolsTokenRefreshResult, error)
- func (c *Client) ReportToolResult(ctx context.Context, params ToolResultParams) (Ack, error)
- func (c *Client) ServeAgent(handler AgentHandler, capability AgentCapability)
- func (c *Client) SessionContext(ctx context.Context, processID string) (SessionContext, error)
- func (c *Client) SessionContextByID(ctx context.Context, sessionID string) (SessionContext, error)
- func (c *Client) SessionEnded(ctx context.Context, params SessionEndedParams) (Ack, error)
- func (c *Client) SessionReady(ctx context.Context, params SessionReadyParams) (Ack, error)
- func (c *Client) Start(ctx context.Context) (ExecutorRegisterResult, error)
- func (c *Client) State() ConnectionState
- func (c *Client) Stop(ctx context.Context, reason string) error
- func (c *Client) UploadArtifact(ctx context.Context, sessionID, name, mimeType string, content []byte) (ArtifactRef, error)
- func (c *Client) WaitReady(ctx context.Context) error
- type CloseError
- type ComputerActionInput
- type ComputerActionRequest
- type ComputerObserveInput
- type ComputerObserveRequest
- type ComputerUseBackend
- type Conn
- type ConnectionState
- type ContentBlock
- type Core
- type CoreOptions
- type CoreSession
- func (s *CoreSession) Assignment() SessionAssignParams
- func (s *CoreSession) Brain() string
- func (s *CoreSession) Client() *Client
- func (s *CoreSession) Context() context.Context
- func (s *CoreSession) ID() string
- func (s *CoreSession) ResolveCwd(cwd string) (string, error)
- func (s *CoreSession) Value(key any, create func() any) any
- func (s *CoreSession) Workspace() string
- type CuaDriver
- type CuaDriverOptions
- type Cursors
- type CustomToolResultResult
- type DaemonHTTPError
- type Dialer
- func InProcessDialer(h *Harness, principal Principal) Dialer
- func ListenNamedPipe(name, token string) (Dialer, func() error, error)
- func ListenUnixSocket(path, token string) (Dialer, func() error, error)
- func NamedPipeDialer(name string) Dialer
- func UnixSocketDialer(path string) Dialer
- func WebSocketDialer(httpClient *http.Client) Dialer
- type DisplayCapability
- type DrainHandler
- type EditInput
- type EnvironmentInfo
- type EvaluatedPermission
- type Executor
- func (e *Executor) AgentCapability() (*AgentCapability, error)
- func (e *Executor) AssignSession(ctx context.Context, params SessionAssignParams) (*Session, error)
- func (e *Executor) Call(ctx context.Context, method string, params, out any) error
- func (e *Executor) CancelTurn(ctx context.Context, params TurnCancelParams) (TurnCancelResult, error)
- func (e *Executor) Capabilities(out any) error
- func (e *Executor) CloseAgentSession(ctx context.Context, params SessionCloseParams) (SessionCloseResult, error)
- func (e *Executor) Drain(ctx context.Context, reason string) (ExecutorDrainResult, error)
- func (e *Executor) ID() string
- func (e *Executor) Info() ExecutorInfo
- func (e *Executor) Protocol() string
- func (e *Executor) RespondCustomToolResult(ctx context.Context, params AgentCustomToolResultParams) (CustomToolResultResult, error)
- func (e *Executor) RespondInteraction(ctx context.Context, params InteractionResponseParams) (InteractionResponseResult, error)
- func (e *Executor) SendTurnInput(ctx context.Context, params TurnInputParams) (Ack, error)
- func (e *Executor) Sessions() []*Session
- func (e *Executor) StartTurn(ctx context.Context, params TurnStartParams) (TurnStartResult, error)
- type ExecutorCapabilitiesUpdateParams
- type ExecutorCloseParams
- type ExecutorDrainParams
- type ExecutorDrainResult
- type ExecutorHeartbeatParams
- type ExecutorHeartbeatResult
- type ExecutorInfo
- type ExecutorLoad
- type ExecutorRegisterParams
- type ExecutorRegisterResult
- type ExecutorResume
- type ExecutorTokenRefreshParams
- type ExecutorTokenRefreshResult
- type ExecutorTokenRequest
- type ExecutorTokenResponse
- type FileAccessFunc
- type FileAccessRequest
- type FileTransferError
- type FileTransferResult
- type FileTransferer
- type FilesCapability
- type FsCapability
- type FsMount
- type FsMountParams
- type FsMountResult
- type FsUnmountParams
- type FsUnmountResult
- type GitCredentialGranter
- type GlobInput
- type GrepInput
- type Handler
- type Harness
- func (h *Harness) DialExecutor(ctx context.Context, path, token string) error
- func (h *Harness) Executors() []*Executor
- func (h *Harness) ServeConn(transport Conn, principal Principal)
- func (h *Harness) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (h *Harness) WaitExecutor(ctx context.Context) (*Executor, error)
- type HarnessMCPChannel
- type HarnessOptions
- type HarnessToolSlot
- type HarnessTools
- type InteractionCancelParams
- type InteractionQuestion
- type InteractionQuestionOption
- type InteractionRequestParams
- type InteractionRequestResult
- type InteractionResponder
- type InteractionResponseParams
- type InteractionResponseResult
- type JSONRPCError
- type JSONRPCErrorData
- type JSONRPCErrorResponse
- type JSONRPCNotification
- type JSONRPCRequest
- type JSONRPCSuccessResponse
- type LaunchFunc
- type LaunchRequest
- type LaunchSpec
- type Lease
- type Limits
- type ListFilesInput
- type LocalToolRoute
- type LocalToolRouteOptions
- type LogEvent
- type LogLevel
- type MCPCapability
- type MCPChannel
- type MCPContentBlock
- type MCPImplementation
- type MCPInitializeParams
- type MCPInitializeResult
- type MCPJSONRPCError
- type MCPJSONRPCErrorResponse
- type MCPJSONRPCNotification
- type MCPJSONRPCRequest
- type MCPJSONRPCSuccessResponse
- type MCPProgressParams
- type MCPServerConfig
- type MCPServerTransport
- type MCPTool
- type MCPToolsCallParams
- type MCPToolsCallResult
- type MCPToolsListParams
- type MCPToolsListResult
- type MethodDirection
- type MethodSpec
- type ModelTokenRefreshParams
- type ModelTokenRefreshResult
- type NotificationMethod
- type Options
- type PackageInstallCommand
- type PackageInstaller
- type PlatformToolRoute
- type PlatformToolRouteOptions
- type Principal
- type ProcessCapability
- type ProcessContext
- type ProcessFileTransfer
- type ProcessListParams
- type ProcessListResult
- type ProcessOptions
- type ProcessPackageInstall
- type ProcessReadParams
- type ProcessReadResult
- type ProcessSignalParams
- type ProcessStartParams
- type ProcessState
- type ProcessStatusParams
- type ProcessWriteParams
- type ProcessWriteResult
- type RPC
- type RPCError
- type ReadInput
- type RemoteBrainCapability
- type Request
- type RequestMethod
- type RouteBackground
- type RouteCall
- type RouteResult
- type RunAs
- type Session
- func (s *Session) CallTool(ctx context.Context, params ToolCallParams) (ToolResultParams, error)
- func (s *Session) CancelTool(ctx context.Context, toolCallID, reason string) (bool, error)
- func (s *Session) Done() <-chan struct{}
- func (s *Session) EndReason() string
- func (s *Session) Executor() *Executor
- func (s *Session) ID() string
- func (s *Session) MCP(ctx context.Context, serverKey string) (*HarnessMCPChannel, error)
- func (s *Session) Ready(ctx context.Context) error
- func (s *Session) Stop(ctx context.Context, reason string) error
- func (s *Session) WorkID() string
- type SessionAssignHandler
- type SessionAssignParams
- type SessionAssignResult
- type SessionCloseParams
- type SessionCloseResult
- type SessionContext
- type SessionEndedParams
- type SessionErrorEvent
- type SessionEvent
- type SessionEventDeltaParams
- type SessionEventParams
- type SessionEventResult
- type SessionFileTransferer
- type SessionFiles
- type SessionFilesCapability
- type SessionFilesOptions
- type SessionMemoryResource
- type SessionReadyParams
- type SessionStatusIdleEvent
- type SessionStatusParams
- type SessionStatusRunningEvent
- type SessionStopHandler
- type SessionStopParams
- type SessionStopResult
- type ShellCapability
- type SkillInstallParams
- type SkillInstallResult
- type SkillInstaller
- type SkillsCapability
- type StopReason
- type TerminalAttachParams
- type TerminalAttachResult
- type TerminalCapability
- type TerminalCloseParams
- type TerminalCloseResult
- type TerminalErrorData
- type TerminalHost
- type TerminalOpenParams
- type TerminalOpenResult
- type ToolCallParams
- type ToolCancelParams
- type ToolCancelResult
- type ToolContext
- type ToolError
- type ToolInput
- type ToolOutput
- type ToolPermission
- type ToolProgressParams
- type ToolResultParams
- type ToolRoute
- type ToolSlot
- type Tools
- type ToolsTokenRefreshParams
- type ToolsTokenRefreshResult
- type TurnCancelParams
- type TurnCancelResult
- type TurnInputParams
- type TurnStartParams
- type TurnStartResult
- type WorkspaceBackupParams
- type WorkspaceBackupResult
- type WorkspaceCapability
- type WriteInput
Constants ¶
const ( // DefaultACPCancelGrace is how long a canceled turn waits for the agent's // cancelled stop before the agent process is killed. DefaultACPCancelGrace = 10 * time.Second // DefaultACPKillGrace is the wait between SIGTERM and SIGKILL of the agent process group. DefaultACPKillGrace = 3 * time.Second // DefaultACPMaxSessions bounds the agent sessions of one ACPAgent. DefaultACPMaxSessions = 8 // DefaultACPResidentSessions is the share of the Core's MaxSessions (in // percent) that resident sessions may use by default; the rest stays for // sessions assigned to the Core as hands. DefaultACPResidentSessions = 75 // PlatformCredentialHarnessModel is the agent capability's // platform_credentials entry for the per-turn model endpoint and token // (turn.start metadata model_base_url, model_token, model_token_expires_at). PlatformCredentialHarnessModel = "harness_model" // PlatformCredentialBrainTools is the platform_credentials entry for the // per-turn tools endpoint and token (turn.start metadata tools_mcp_url, // tools_mcp_token, tools_mcp_token_expires_at), contract 1.4.0. PlatformCredentialBrainTools = "brain_tools" )
const ( // ACPProfileDSH is bma-dsh-acp (ADR-0027), the default. ACPProfileDSH = "dsh" // ACPProfileClaudeCode is the official claude-agent-acp, unmodified (see // agent_acp_claude.go). It uses only the node owner's own Claude // credentials and never the platform's model endpoint. ACPProfileClaudeCode = "claude-code" )
ACP profiles: which agent the ACPAgent hosts.
const ( // MachineIDEnv is the environment variable that carries the machine id of // a machine-scoped executor (injected by the machine pool template). MachineIDEnv = "BMA_MACHINE_ID" DefaultBaseURL = "https://api.bma.beeos.ai" DefaultRequestTimeout = 30 * time.Second // DefaultMaxReconnectAttempts is 0: reconnect until Stop, as gRPC's // connection backoff and long-running agents (GitHub Actions runner, // Buildkite agent) do. DefaultMaxReconnectAttempts = 0 DefaultReconnectBaseDelay = time.Second // DefaultToolResultRetryAttempts is the total number of tool.result attempts. DefaultToolResultRetryAttempts = 5 // DefaultToolResultRetryBaseDelay is the first retry backoff for tool.result. DefaultToolResultRetryBaseDelay = 250 * time.Millisecond )
const ( DefaultCoreMaxSessions = 16 DefaultCoreMaxMCPServers = 4 DefaultCoreBashTimeout = 10 * time.Minute DefaultCoreMaxOutputBytes = 1024 * 1024 DefaultCoreInlineResultBytes = 48 * 1024 // DefaultMaxArtifactBytes bounds one artifact upload (v1.1 §6.5). DefaultMaxArtifactBytes = 16 * 1024 * 1024 )
const ( FileOperationRead = "read" FileOperationWrite = "write" )
File operations a FileAccessFunc is asked about.
const ( SessionMountUploads = "uploads" SessionMountSkills = "skills" SessionMountOutputs = "outputs" )
The mounted directories of a session.
const ( AgentErrorCodeOutputLimitReached = "output_limit_reached" AgentErrorCodeContextTooLarge = "context_too_large" AgentErrorCodeModelStreamIdle = "model_stream_idle" AgentErrorCodeAgentError = "agent_error" AgentErrorCodeAgentAuthRequired = "agent_auth_required" AgentErrorCodeAgentProtocolError = "agent_protocol_error" )
AgentErrorCode values. Stop code table: the error types an agent executor reports for a turn that ended failed, so every agent (Go ACP harness, brain hosts, local desktop agents) says the same thing for the same cause. output_limit_reached: the model reply was cut at its output-token limit (ACP stopReason max_tokens, DSH max-tokens, finish_reason length). context_too_large: the conversation does not fit the model context window even after compaction. model_stream_idle: the model stream sent no data for the idle limit (default 90 s). agent_error: any other failure of the agent. agent_unavailable: the agent process is gone or did not answer a cancel in time. agent_auth_required: the agent needs credentials it does not have. agent_protocol_error: the agent rejected the request as malformed or unsupported. A code is the type of session.error; an executor whose SDK cannot set the type yet (structured_errors false) puts it first in the message as '<code>: <detail>', and the platform reads both forms. The platform keeps the code in error.code and projects a type outside the official session.error union to unknown_error; a platform may map a code to an official type itself (context_too_large to compaction_limit_reached_error, ADR-0010). Executors report only these values; a new cause adds a value here first.
const ( AgentEventTypeAgentMessage = "agent.message" AgentEventTypeAgentThinking = "agent.thinking" AgentEventTypeAgentToolUse = "agent.tool_use" AgentEventTypeAgentToolResult = "agent.tool_result" AgentEventTypeAgentCustomToolUse = "agent.custom_tool_use" AgentEventTypeAgentMcpToolUse = "agent.mcp_tool_use" AgentEventTypeAgentMcpToolResult = "agent.mcp_tool_result" AgentEventTypeSessionStatusRunning = "session.status_running" AgentEventTypeSessionStatusIdle = "session.status_idle" AgentEventTypeSessionError = "session.error" )
AgentEventType values. Durable events an agent executor emits with session.event. Names and members follow Anthropic Managed Agents session events. user.* events are written by the platform, never by the executor.
const ( AgentInputBlockTypeText = "text" AgentInputBlockTypeFile = "file" )
AgentInputBlockType values. Agent input block type.
const ( ChannelControl = "control" ChannelMCP = "mcp" )
ChannelScope values. Channels a short-lived executor JWT may open.
const ( ComputerActionClick = "click" ComputerActionType = "type" ComputerActionKey = "key" ComputerActionScroll = "scroll" ComputerActionDrag = "drag" )
ComputerAction values. Input actions accepted by the computer_action tool.
const ( ConnectionStateDisconnected = "disconnected" ConnectionStateConnecting = "connecting" ConnectionStateRegistered = "registered" ConnectionStateReady = "ready" ConnectionStateDraining = "draining" ConnectionStateClosed = "closed" )
ConnectionState values. Executor control channel state machine.
const ( ContentBlockTypeText = "text" ContentBlockTypeImage = "image" ContentBlockTypeResource = "resource" ContentBlockTypeArtifact = "artifact" )
ContentBlockType values. Tool result content block type.
const ( EventDeltaTypeAgentMessage = "agent.message" EventDeltaTypeAgentThinking = "agent.thinking" )
EventDeltaType values. Durable event type a streaming preview belongs to.
const ( FileTransferUpload = "upload" FileTransferDownload = "download" )
FileTransferDirection values. File transfer direction relative to the machine.
const ( InteractionCancelReasonResolvedLocally = "resolved_locally" InteractionCancelReasonTurnCanceled = "turn_canceled" InteractionCancelReasonExpired = "expired" InteractionCancelReasonToolCanceled = "tool_canceled" )
InteractionCancelReason values. Why the executor withdrew an open interaction.
const ( InteractionKindPermission = "permission" InteractionKindQuestion = "question" )
InteractionKind values. Interaction kinds; they map 1:1 to platform agent interactions.
const ( InteractionOutcomeAllow = "allow" InteractionOutcomeDeny = "deny" InteractionOutcomeAnswered = "answered" InteractionOutcomeExpired = "expired" InteractionOutcomeCanceled = "canceled" )
InteractionOutcome values. How the platform resolved an interaction. allow/deny answer permission, answered answers question, expired and canceled close either kind without an answer.
const ( InteractionScopeOnce = "once" InteractionScopeSession = "session" )
InteractionScope values. How long a permission grant lasts on the executor: this tool use only, or the rest of the session.
const ( CodeParseError = -32700 CodeInvalidRequest = -32600 CodeMethodNotFound = -32601 CodeInvalidParams = -32602 CodeInternalError = -32603 CodeForbidden = -32001 CodeNotFound = -32002 CodeLeaseExpired = -32003 CodeTimeout = -32004 CodeCanceled = -32005 CodePayloadTooLarge = -32006 CodeSessionNotActive = -32007 CodeExecutorBusy = -32009 CodeUnsupportedProtocol = -32010 CodeConflict = -32013 )
JSONRPCErrorCode values. Executor protocol JSON-RPC error codes. -32011..-32013 are v1.1 additions.
const ( MCPConnectionOriginService = "service" MCPConnectionOriginEnvironment = "environment" )
MCPConnectionOrigin values. Who connects the MCP server. environment means the executor starts/connects it; service means the harness connects.
const ( MCPTransportTypeStdio = "stdio" MCPTransportTypeHttp = "http" )
MCPTransportType values.
const ( PackageManagerApt = "apt" PackageManagerPip = "pip" PackageManagerNpm = "npm" )
PackageManager values. Package manager for process.start package_install.
const ( PermissionModeAlwaysAllow = "always_allow" PermissionModeAlwaysAsk = "always_ask" )
PermissionMode values. Tool permission mode; always_ask means the harness already resolved approval.
const ( ProcessRunning = "running" ProcessExited = "exited" ProcessFailed = "failed" ProcessKilled = "killed" )
ProcessStateName values. Process state (v1.1 §3.3).
const ( StreamStdout = "stdout" StreamStderr = "stderr" )
ProcessStream values. Process output stream (v1.1 §3.2).
const ( ProtocolV1 = "bma.executor.v1" ProtocolV11 = "bma.executor.v1.1" )
ProtocolVersion values. Value of both the WebSocket subprotocol and executor.register protocol. A v1.1 server serves v1 executors and never sends them v1.1 methods.
const ( SessionEventTypeAgentToolResult = "agent.tool_result" SessionEventTypeAgentMessage = "agent.message" SessionEventTypeAgentThinking = "agent.thinking" SessionEventTypeAgentToolUse = "agent.tool_use" SessionEventTypeAgentCustomToolUse = "agent.custom_tool_use" SessionEventTypeAgentMcpToolUse = "agent.mcp_tool_use" SessionEventTypeAgentMcpToolResult = "agent.mcp_tool_result" SessionEventTypeSessionStatusRunning = "session.status_running" SessionEventTypeSessionStatusIdle = "session.status_idle" SessionEventTypeSessionError = "session.error" )
SessionEventType values. Durable event types an executor may emit. Event names follow Anthropic Managed Agents; the executor must not invent new names. A tool executor emits agent.tool_result only; an agent executor (capability agent) emits every type, shaped as schemas/agent.json AgentEvent.
const ( SessionStatusStarting = "starting" SessionStatusRunning = "running" SessionStatusIdle = "idle" SessionStatusStopping = "stopping" SessionStatusStopped = "stopped" SessionStatusError = "error" )
SessionStatus values. Lifecycle status reported by the executor.
const ( StdinOpen = "open" StdinClosed = "closed" )
StdinMode values. process.start stdin mode. Empty or "closed" closes stdin at start; "open" keeps it open for process.write.
const ( StopReasonTypeEndTurn = "end_turn" StopReasonTypeRetriesExhausted = "retries_exhausted" )
StopReasonType values. Anthropic stop_reason types an executor may report. requires_action is not in the list: the platform projects it from open interactions.
const ( ToolNameBash = "bash" ToolNameRead = "read" ToolNameWrite = "write" ToolNameEdit = "edit" ToolNameGlob = "glob" ToolNameGrep = "grep" ToolNameListFiles = "list_files" ToolNameComputerObserve = "computer_observe" ToolNameComputerAction = "computer_action" )
ToolName values. Built-in tool names. bmad serves bash only and answers -32012 for the rest.
const ( ToolOutcomeSucceeded = "succeeded" ToolOutcomeFailed = "failed" ToolOutcomeCanceled = "canceled" )
ToolOutcome values. Tool outcome.
const ( TurnOutcomeCompleted = "completed" TurnOutcomeCanceled = "canceled" TurnOutcomeFailed = "failed" )
TurnOutcome values. BMA extension on session.status_idle: how the turn ended.
const ( MethodExecutorRegister = "executor.register" MethodExecutorHeartbeat = "executor.heartbeat" MethodExecutorTokenRefresh = "executor.token.refresh" MethodExecutorCapabilitiesUpdate = "executor.capabilities.update" MethodExecutorDrain = "executor.drain" MethodExecutorClose = "executor.close" MethodSessionAssign = "session.assign" MethodSessionReady = "session.ready" MethodSessionEvent = "session.event" MethodSessionStatus = "session.status" MethodSessionStop = "session.stop" MethodSessionEnded = "session.ended" MethodToolCall = "tool.call" MethodToolResult = "tool.result" MethodToolCancel = "tool.cancel" MethodToolProgress = "tool.progress" MethodProcessStart = "process.start" MethodProcessRead = "process.read" MethodProcessWrite = "process.write" MethodProcessInterrupt = "process.interrupt" MethodProcessTerminate = "process.terminate" MethodProcessList = "process.list" MethodProcessStatus = "process.status" MethodTerminalOpen = "terminal.open" MethodTerminalAttach = "terminal.attach" MethodTerminalClose = "terminal.close" MethodSkillInstall = "skill.install" MethodWorkspaceBackup = "workspace.backup" MethodFsMount = "fs.mount" MethodFsUnmount = "fs.unmount" MethodTurnStart = "turn.start" MethodTurnInput = "turn.input" MethodTurnCancel = "turn.cancel" MethodSessionClose = "session.close" MethodSessionEventDelta = "session.event_delta" MethodInteractionRequest = "interaction.request" MethodInteractionResponse = "interaction.response" MethodAgentCustomToolResult = "agent.custom_tool_result" MethodInteractionCancel = "interaction.cancel" MethodModelTokenRefresh = "model_token.refresh" MethodToolsTokenRefresh = "tools_token.refresh" )
const ( DefaultHarnessHeartbeatInterval = 15 * time.Second DefaultHarnessLeaseTTL = 60 * time.Second )
const ( // MaxProcessesPerSession bounds running processes; ended processes are // retained separately (see retainEndedLocked). MaxProcessesPerSession = 64 ProcessBufferBytes = 1024 * 1024 )
Process limits (v1.1 §1.3, §3). They match DefaultLimits.
const ( ReasonWorkspaceUnavailable = "workspace_unavailable" // The request leaves what the executor's local policy allows. ReasonWorkspaceBoundary = "workspace_boundary" // The request writes where the local policy only allows reads. ReasonWorkspaceReadOnly = "workspace_read_only" // The session is not one this machine serves (an owner check failed). ReasonSessionRejected = "session_rejected" // The local user denied the access. ReasonLocalConfirmationDenied = "local_confirmation_denied" // Nobody answered the local confirmation in time. ReasonLocalConfirmationExpired = "local_confirmation_expired" // The process could not be started. ReasonSpawnFailed = "spawn_failed" // A process.start replay changed the spec of an existing process id. ReasonProcessIDSpecMismatch = "process_id_spec_mismatch" )
Recommended error.data.reason values (contracts/bma README, open set): an executor that refuses a process.start or a tool.call answers with a JSON-RPC error whose data.reason is one of these, and BMA passes it to the tool result's error_code and the turn's session.error.code unchanged. Any other value is passed through as well. TypeScript ErrorReason and Python ErrorReason carry the same names and values.
const ( // RouteOutcomeNotForwarded: the call was refused and certainly did not // run (policy, approval, a stale turn, hands offline); it is safe to ask // again, for example once approved. RouteOutcomeNotForwarded = "not_forwarded" // RouteOutcomeExecuted: the tool ran; RouteResult.IsError says whether the // tool itself failed. RouteOutcomeExecuted = "executed" // RouteOutcomeUnknown: the call may have run (the connection broke after // it was sent, the hands restarted); do not blindly run it again. RouteOutcomeUnknown = "unknown" )
The three outcomes of a tool call, as the platform's tool gateway says them (ADR-0005).
const DefaultACPSystemPrompt = "You are an agent running on the user's computer through BMA (BeeOS Managed Agents).\n" +
"Your tools run on this computer, in the working directory %s; use paths under it.\n" +
"Be concise. When a task is done, say what you did."
DefaultACPSystemPrompt is the base system prompt of a local brain; the agent definition's system instructions follow it.
const (
IOModePTY = "pty"
)
IOMode values. process.start io_mode. "pty" runs the command on a 24x80 pseudo-terminal: stdout is the PTY output, stdin writes go to the PTY and close_stdin is rejected. Requires process.pty.
const MaxFileTransferBytes = 1 << 30
MaxFileTransferBytes bounds one file transfer (v1.1 §6.2): 1 GiB.
const MetadataAgentSessionID = "agent_session_id"
MetadataAgentSessionID is the process.start metadata key naming the agent session a process runs for (the session SessionContext and SessionFiles look up).
const (
StderrMerge = "merge"
)
StderrMode values. process.start stderr mode. "merge" redirects stderr into stdout at the OS level so one cursor covers both.
const ToolNameAskUserQuestion = "ask_user_question"
ToolNameAskUserQuestion is the host tool of a local brain that asks the user (see agent_acp_host_tools.go).
Variables ¶
var ( // ErrNotConnected is returned when a call is attempted before the channel opens. ErrNotConnected = errors.New("bmaexecutor: executor channel is not connected") // ErrClientStopped is returned after Stop or a terminal close code. ErrClientStopped = errors.New("bmaexecutor: client stopped") // ErrReplaced is Err after the harness closed with 4004: a newer // connection for this executor is authoritative and this one must stop. ErrReplaced = errors.New("bmaexecutor: executor connection was replaced (4004)") // ErrReconnectExhausted is Err after a positive MaxReconnectAttempts // failed; it wraps the last failure. ErrReconnectExhausted = errors.New("bmaexecutor: executor reconnect attempts exhausted") // ErrCredentialRejected is wrapped by the token request error when the // token endpoint answers 401 or 403 (an invalid or revoked environment // key or machine token). A reconnect does not retry it: the client ends // with it as Err. A TokenSource may wrap it for the same effect. ErrCredentialRejected = errors.New("bmaexecutor: executor credential rejected") // ErrRegistrationRefused is Err after the platform refused the // executor's registration maxRefusedRegistrations times in a row: the // close 4002 "runtime registration refused" right after // executor.register, or an executor.register error for the executor's // capabilities. It is a configuration error (a machine-scoped executor // must declare the process or agent capability) that reconnecting // cannot fix. It wraps the last refusal. ErrRegistrationRefused = errors.New("bmaexecutor: executor registration refused") )
var ( // ErrSessionEnded is returned for requests on a session that has ended. ErrSessionEnded = errors.New("bmaexecutor: session ended") // ErrToolOutcomeUnknown means the executor was lost (lease expiry, // executor.close, session ended, or a restarted executor that no longer // reports the session) before a tool.result arrived. The tool may or may // not have run; the caller decides whether a retry is safe. ErrToolOutcomeUnknown = errors.New("bmaexecutor: tool outcome unknown: executor lost before tool.result") // ErrAssignRejected is returned when session.assign answers accepted=false. ErrAssignRejected = errors.New("bmaexecutor: executor rejected session.assign") )
var Calls = struct { SessionReady CallMethod[SessionReadyParams, Ack] SessionEvent CallMethod[SessionEventParams, SessionEventResult] SessionEnded CallMethod[SessionEndedParams, Ack] ToolResult CallMethod[ToolResultParams, Ack] InteractionRequest CallMethod[InteractionRequestParams, InteractionRequestResult] InteractionCancel CallMethod[InteractionCancelParams, Ack] ModelTokenRefresh CallMethod[ModelTokenRefreshParams, ModelTokenRefreshResult] ToolsTokenRefresh CallMethod[ToolsTokenRefreshParams, ToolsTokenRefreshResult] }{ SessionReady: CallMethod[SessionReadyParams, Ack]{Method: "session.ready"}, SessionEvent: CallMethod[SessionEventParams, SessionEventResult]{Method: "session.event"}, SessionEnded: CallMethod[SessionEndedParams, Ack]{Method: "session.ended"}, ToolResult: CallMethod[ToolResultParams, Ack]{Method: "tool.result"}, InteractionRequest: CallMethod[InteractionRequestParams, InteractionRequestResult]{Method: "interaction.request"}, InteractionCancel: CallMethod[InteractionCancelParams, Ack]{Method: "interaction.cancel"}, ModelTokenRefresh: CallMethod[ModelTokenRefreshParams, ModelTokenRefreshResult]{Method: "model_token.refresh"}, ToolsTokenRefresh: CallMethod[ToolsTokenRefreshParams, ToolsTokenRefreshResult]{Method: "tools_token.refresh"}, }
Calls are the executor-to-harness requests a client sends: Calls.SessionEvent.Call(ctx, client, params).
var ErrAgentSessionClosed = errors.New("bmaexecutor: agent session closed")
ErrAgentSessionClosed is returned by AgentTurn methods after session.close.
ErrComputerUseUnavailable is returned by NewCuaDriver when the driver or its interactive-session daemon cannot be used; leave CoreOptions.ComputerUse nil then.
var ErrMachineTokenRequired = errors.New("bmaexecutor: a machine-scoped executor (machine daemon token in EnvironmentKey, empty EnvironmentID) is required")
ErrMachineTokenRequired is returned by the machine-token HTTP features (SessionContext, SessionContextByID, SessionFiles) of a client that is not a machine-scoped executor: Options.EnvironmentKey must hold the machine daemon token and Options.EnvironmentID must be empty.
var ErrNamedPipeUnsupported = errors.New("bmaexecutor: Windows named pipes are not supported on this platform")
ErrNamedPipeUnsupported is returned by the named pipe transport on platforms other than Windows.
var ErrSessionContextNotFound = errors.New("bmaexecutor: session context not found")
ErrSessionContextNotFound is returned when the process is not on this machine (or ended more than 15 minutes ago), or the session is not bound to this machine.
var Methods = map[string]MethodSpec{ MethodExecutorRegister: {Name: MethodExecutorRegister, Direction: DirectionExecutorToHarness, Notification: false, Since: "bma.executor.v1", Capability: "", IdempotentBy: ""}, MethodExecutorHeartbeat: {Name: MethodExecutorHeartbeat, Direction: DirectionExecutorToHarness, Notification: false, Since: "bma.executor.v1", Capability: "", IdempotentBy: ""}, MethodExecutorTokenRefresh: {Name: MethodExecutorTokenRefresh, Direction: DirectionExecutorToHarness, Notification: false, Since: "bma.executor.v1.1", Capability: "", IdempotentBy: ""}, MethodExecutorCapabilitiesUpdate: {Name: MethodExecutorCapabilitiesUpdate, Direction: DirectionExecutorToHarness, Notification: true, Since: "bma.executor.v1", Capability: "", IdempotentBy: ""}, MethodExecutorDrain: {Name: MethodExecutorDrain, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1", Capability: "", IdempotentBy: ""}, MethodExecutorClose: {Name: MethodExecutorClose, Direction: DirectionBidirectional, Notification: true, Since: "bma.executor.v1", Capability: "", IdempotentBy: ""}, MethodSessionAssign: {Name: MethodSessionAssign, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1", Capability: "", IdempotentBy: ""}, MethodSessionReady: {Name: MethodSessionReady, Direction: DirectionExecutorToHarness, Notification: false, Since: "bma.executor.v1", Capability: "", IdempotentBy: ""}, MethodSessionEvent: {Name: MethodSessionEvent, Direction: DirectionExecutorToHarness, Notification: false, Since: "bma.executor.v1", Capability: "", IdempotentBy: "jsonrpc_id"}, MethodSessionStatus: {Name: MethodSessionStatus, Direction: DirectionExecutorToHarness, Notification: true, Since: "bma.executor.v1", Capability: "", IdempotentBy: ""}, MethodSessionStop: {Name: MethodSessionStop, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1", Capability: "", IdempotentBy: ""}, MethodSessionEnded: {Name: MethodSessionEnded, Direction: DirectionExecutorToHarness, Notification: false, Since: "bma.executor.v1", Capability: "", IdempotentBy: ""}, MethodToolCall: {Name: MethodToolCall, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1", Capability: "", IdempotentBy: ""}, MethodToolResult: {Name: MethodToolResult, Direction: DirectionExecutorToHarness, Notification: false, Since: "bma.executor.v1", Capability: "", IdempotentBy: "tool_call_id"}, MethodToolCancel: {Name: MethodToolCancel, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1", Capability: "", IdempotentBy: ""}, MethodToolProgress: {Name: MethodToolProgress, Direction: DirectionExecutorToHarness, Notification: true, Since: "bma.executor.v1", Capability: "", IdempotentBy: ""}, MethodProcessStart: {Name: MethodProcessStart, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1.1", Capability: "process.enabled", IdempotentBy: "session_id+process_id"}, MethodProcessRead: {Name: MethodProcessRead, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1.1", Capability: "process.enabled", IdempotentBy: ""}, MethodProcessWrite: {Name: MethodProcessWrite, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1.1", Capability: "process.enabled", IdempotentBy: ""}, MethodProcessInterrupt: {Name: MethodProcessInterrupt, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1.1", Capability: "process.enabled", IdempotentBy: ""}, MethodProcessTerminate: {Name: MethodProcessTerminate, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1.1", Capability: "process.enabled", IdempotentBy: ""}, MethodProcessList: {Name: MethodProcessList, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1.1", Capability: "process.enabled", IdempotentBy: ""}, MethodProcessStatus: {Name: MethodProcessStatus, Direction: DirectionExecutorToHarness, Notification: true, Since: "bma.executor.v1.1", Capability: "process.enabled", IdempotentBy: ""}, MethodTerminalOpen: {Name: MethodTerminalOpen, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1.1", Capability: "terminal.enabled", IdempotentBy: "terminal_id"}, MethodTerminalAttach: {Name: MethodTerminalAttach, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1.1", Capability: "terminal.enabled", IdempotentBy: ""}, MethodTerminalClose: {Name: MethodTerminalClose, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1.1", Capability: "terminal.enabled", IdempotentBy: "terminal_id"}, MethodSkillInstall: {Name: MethodSkillInstall, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1.1", Capability: "skills.install", IdempotentBy: "skill_id+revision_id+digest"}, MethodWorkspaceBackup: {Name: MethodWorkspaceBackup, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1.1", Capability: "workspace.backup", IdempotentBy: "backup_id"}, MethodFsMount: {Name: MethodFsMount, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1.1", Capability: "fs.fuse", IdempotentBy: "session_id+view"}, MethodFsUnmount: {Name: MethodFsUnmount, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1.1", Capability: "fs.fuse", IdempotentBy: "session_id"}, MethodTurnStart: {Name: MethodTurnStart, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1.1", Capability: "agent", IdempotentBy: "turn_id"}, MethodTurnInput: {Name: MethodTurnInput, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1.1", Capability: "agent", IdempotentBy: "input_id"}, MethodTurnCancel: {Name: MethodTurnCancel, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1.1", Capability: "agent", IdempotentBy: ""}, MethodSessionClose: {Name: MethodSessionClose, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1.1", Capability: "agent", IdempotentBy: ""}, MethodSessionEventDelta: {Name: MethodSessionEventDelta, Direction: DirectionExecutorToHarness, Notification: true, Since: "bma.executor.v1.1", Capability: "agent", IdempotentBy: ""}, MethodInteractionRequest: {Name: MethodInteractionRequest, Direction: DirectionExecutorToHarness, Notification: false, Since: "bma.executor.v1.1", Capability: "agent", IdempotentBy: "interaction_id"}, MethodInteractionResponse: {Name: MethodInteractionResponse, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1.1", Capability: "agent", IdempotentBy: "interaction_id"}, MethodAgentCustomToolResult: {Name: MethodAgentCustomToolResult, Direction: DirectionHarnessToExecutor, Notification: false, Since: "bma.executor.v1.1", Capability: "agent", IdempotentBy: "tool_use_id"}, MethodInteractionCancel: {Name: MethodInteractionCancel, Direction: DirectionExecutorToHarness, Notification: false, Since: "bma.executor.v1.1", Capability: "agent", IdempotentBy: "interaction_id"}, MethodModelTokenRefresh: {Name: MethodModelTokenRefresh, Direction: DirectionExecutorToHarness, Notification: false, Since: "bma.executor.v1.1", Capability: "agent", IdempotentBy: ""}, MethodToolsTokenRefresh: {Name: MethodToolsTokenRefresh, Direction: DirectionExecutorToHarness, Notification: false, Since: "bma.executor.v1.1", Capability: "agent", IdempotentBy: ""}, }
Methods is the complete method catalog.
var Notifications = struct { ExecutorCapabilitiesUpdate NotificationMethod[ExecutorCapabilitiesUpdateParams] SessionStatus NotificationMethod[SessionStatusParams] ToolProgress NotificationMethod[ToolProgressParams] ProcessStatus NotificationMethod[ProcessStatusParams] SessionEventDelta NotificationMethod[SessionEventDeltaParams] }{ ExecutorCapabilitiesUpdate: NotificationMethod[ExecutorCapabilitiesUpdateParams]{Method: "executor.capabilities.update"}, SessionStatus: NotificationMethod[SessionStatusParams]{Method: "session.status"}, ToolProgress: NotificationMethod[ToolProgressParams]{Method: "tool.progress"}, ProcessStatus: NotificationMethod[ProcessStatusParams]{Method: "process.status"}, SessionEventDelta: NotificationMethod[SessionEventDeltaParams]{Method: "session.event_delta"}, }
Notifications are the executor-to-harness notifications a client sends: Notifications.ToolProgress.Notify(ctx, client, params).
var Requests = struct { ProcessStart RequestMethod[ProcessStartParams, ProcessState] ProcessRead RequestMethod[ProcessReadParams, ProcessReadResult] ProcessWrite RequestMethod[ProcessWriteParams, ProcessWriteResult] ProcessInterrupt RequestMethod[ProcessSignalParams, ProcessState] ProcessTerminate RequestMethod[ProcessSignalParams, ProcessState] ProcessList RequestMethod[ProcessListParams, ProcessListResult] TerminalOpen RequestMethod[TerminalOpenParams, TerminalOpenResult] TerminalAttach RequestMethod[TerminalAttachParams, TerminalAttachResult] TerminalClose RequestMethod[TerminalCloseParams, TerminalCloseResult] SkillInstall RequestMethod[SkillInstallParams, SkillInstallResult] WorkspaceBackup RequestMethod[WorkspaceBackupParams, WorkspaceBackupResult] FsMount RequestMethod[FsMountParams, FsMountResult] FsUnmount RequestMethod[FsUnmountParams, FsUnmountResult] AgentCustomToolResult RequestMethod[AgentCustomToolResultParams, CustomToolResultResult] }{ ProcessStart: RequestMethod[ProcessStartParams, ProcessState]{Method: "process.start"}, ProcessRead: RequestMethod[ProcessReadParams, ProcessReadResult]{Method: "process.read"}, ProcessWrite: RequestMethod[ProcessWriteParams, ProcessWriteResult]{Method: "process.write"}, ProcessInterrupt: RequestMethod[ProcessSignalParams, ProcessState]{Method: "process.interrupt"}, ProcessTerminate: RequestMethod[ProcessSignalParams, ProcessState]{Method: "process.terminate"}, ProcessList: RequestMethod[ProcessListParams, ProcessListResult]{Method: "process.list"}, TerminalOpen: RequestMethod[TerminalOpenParams, TerminalOpenResult]{Method: "terminal.open"}, TerminalAttach: RequestMethod[TerminalAttachParams, TerminalAttachResult]{Method: "terminal.attach"}, TerminalClose: RequestMethod[TerminalCloseParams, TerminalCloseResult]{Method: "terminal.close"}, SkillInstall: RequestMethod[SkillInstallParams, SkillInstallResult]{Method: "skill.install"}, WorkspaceBackup: RequestMethod[WorkspaceBackupParams, WorkspaceBackupResult]{Method: "workspace.backup"}, FsMount: RequestMethod[FsMountParams, FsMountResult]{Method: "fs.mount"}, FsUnmount: RequestMethod[FsUnmountParams, FsUnmountResult]{Method: "fs.unmount"}, AgentCustomToolResult: RequestMethod[AgentCustomToolResultParams, CustomToolResultResult]{Method: "agent.custom_tool_result"}, }
Requests are the harness-to-executor requests a client serves: Requests.ProcessStart.Handle(client, fn).
Functions ¶
func ApprovalID ¶ added in v1.4.0
ApprovalID is the interaction id to ask a tool call's approval under (InteractionRequestParams.InteractionID) and to present with the call (RouteCall.ApprovalID): "appr_" and 24 hex characters of sha256 over session, turn and call id, NUL separated (ADR-0027). It is the same after a reconnect or an executor restart, so the platform keeps one interaction per call and an approval already answered is not asked again. The turn is part of it because providers may reuse call ids such as "call_0" in every turn.
func NamedPipeListener ¶
NamedPipeListener listens on the Windows named pipe \\.\pipe\<name> for the current user only (remote clients are refused). Serve Harness on it, as on a Unix socket listener.
func NewParams ¶
NewParams returns a pointer to a zero params object for method, or nil for an unknown method.
func NewResult ¶
NewResult returns a pointer to a zero result for a request method, or nil for a notification or an unknown method.
func NewToolInput ¶
func NewToolInput(input ToolInput) json.RawMessage
NewToolInput encodes a built-in tool input for ToolCallParams.Input.
func Pipe ¶
Pipe returns the two ends of an in-process connection that negotiated protocol: one for the executor (Client), one for the harness (Harness.ServeConn). Frames are copied, so neither side can mutate the other's buffers.
func RequestID ¶
RequestID returns the JSON-RPC id of the inbound request whose handler received ctx (the idempotency key of retried requests), or "".
func SendExecutorCapabilitiesUpdate ¶
func SendExecutorCapabilitiesUpdate(ctx context.Context, rpc RPC, params ExecutorCapabilitiesUpdateParams) error
SendExecutorCapabilitiesUpdate sends the executor.capabilities.update notification.
func SendExecutorClose ¶
func SendExecutorClose(ctx context.Context, rpc RPC, params ExecutorCloseParams) error
SendExecutorClose sends the executor.close notification.
func SendProcessStatus ¶
func SendProcessStatus(ctx context.Context, rpc RPC, params ProcessStatusParams) error
SendProcessStatus sends the process.status notification.
func SendSessionEventDelta ¶
func SendSessionEventDelta(ctx context.Context, rpc RPC, params SessionEventDeltaParams) error
SendSessionEventDelta sends the session.event_delta notification.
func SendSessionStatus ¶
func SendSessionStatus(ctx context.Context, rpc RPC, params SessionStatusParams) error
SendSessionStatus sends the session.status notification.
func SendToolProgress ¶
func SendToolProgress(ctx context.Context, rpc RPC, params ToolProgressParams) error
SendToolProgress sends the tool.progress notification.
func StaticToken ¶
func StaticToken(wsURL, token string) func(context.Context) (ExecutorTokenResponse, error)
StaticToken is a TokenSource for a harness reached directly, typically a local harness. token may be empty when the harness has no Authenticate hook.
Types ¶
type ACPAgent ¶ added in v1.3.0
type ACPAgent struct {
// contains filtered or unexported fields
}
ACPAgent hosts an ACP agent process; see the comment at the top of agent_acp.go.
func NewACPAgent ¶ added in v1.3.0
func NewACPAgent(ctx context.Context, opts ACPAgentOptions) (*ACPAgent, error)
NewACPAgent starts the agent process, checks it (ACP initialize, the six platform tools) and starts the model proxy. Serve it with client.ServeAgent(agent, agent.Capability()).
func (*ACPAgent) Capability ¶ added in v1.3.0
func (a *ACPAgent) Capability() AgentCapability
Capability is the agent capability to serve: one harness, in harnesses[] and in the deprecated harness member.
func (*ACPAgent) CloseSession ¶ added in v1.3.0
func (*ACPAgent) MaxResidentSessions ¶ added in v1.5.0
MaxResidentSessions implements AgentSessionSuspender.
func (*ACPAgent) OpenTurn ¶ added in v1.3.0
func (a *ACPAgent) OpenTurn(ctx context.Context, params TurnStartParams) (TurnStartResult, error)
func (*ACPAgent) SuspendSession ¶ added in v1.5.0
SuspendSession implements AgentSessionSuspender: it releases an idle session's agent session (ACP session/close: the agent frees the memory or process and keeps the conversation for session/load) and its Core session. The next OpenTurn of the session loads the conversation again.
func (*ACPAgent) WaitPrewarm ¶ added in v1.4.0
WaitPrewarm waits for the background prewarm of NewACPAgent and returns its error. It returns nil at once when the profile has no prewarm (ACPProfileDSH) or ACPAgentOptions.DisablePrewarm is set.
type ACPAgentOptions ¶ added in v1.3.0
type ACPAgentOptions struct {
// Profile selects the hosted agent: ACPProfileDSH (default) or
// ACPProfileClaudeCode. The Claude Code profile rejects PlatformModel and
// ignores Upstream and the platform's model credential: the agent talks to
// its model with the node owner's own credentials, which the owner
// configures for Claude Code itself (its login under HOME, or Env such as
// ANTHROPIC_API_KEY / a third-party provider's variables); the SDK never
// reads, forwards or logs them.
Profile string
// Command is the agent's argv, for example {"/opt/bma/bma-dsh-acp"} or
// {"/opt/bma/node", "/opt/bma/bma-dsh-acp.mjs"}. Command[0] must be an
// absolute path: the agent is never looked up on PATH (a user's own dsh
// there must not be started by mistake).
Command []string
// Env adds KEY=VALUE entries to the agent's environment (PATH, HOME, USER, LANG and TMPDIR come from the executor).
Env []string
// StateDir holds the agent's state (BMA_DSH_ACP_HOME = StateDir).
StateDir string
// Core runs the tools.
Core *Core
// AllowedRoots bound a turn's cwd (default: Core's work root). A turn
// without cwd works in Core's per-session workspace.
AllowedRoots []string
// Upstream is the model endpoint used when the platform hands none.
// Required unless PlatformModel.
Upstream ACPModelUpstream
// PlatformModel asks the platform for the per-turn model credential
// (agent capability platform_credentials: harness_model), as a sandbox
// machine of the platform does. Without Upstream a turn the platform
// hands no credential fails (session.error); it is never sent elsewhere.
PlatformModel bool
// PlatformTools declares platform_credentials brain_tools: this machine
// may be the brain of a session whose hands are on another machine
// (ADR-0029). The platform then hands the turn its tools endpoint and token
// (turn.start metadata tools_mcp_*) and every tool call of that turn goes
// there, never to this machine's Core (fail closed). A turn without
// tools_mcp_* runs its tools here.
PlatformTools bool
// AskUserQuestion offers the DSH agent the ask_user_question tool (see
// agent_acp_host_tools.go): a question is a custom tool call of the session
// (capability custom_tools), so turn it on only when the session's clients
// answer custom tool calls (user.custom_tool_result); a client that does not
// leaves the session waiting.
AskUserQuestion bool
// ToolPolicy is the host's ceiling on the permission of tools (tool name
// to allow, ask or deny): the permission of a tool in a turn is the
// stricter of this value and what the platform's turn.start
// metadata.tool_policy and the permission mode give (deny over ask over
// allow), so the platform and the mode can only tighten it, never loosen
// it. A tool it does not name is not capped. A host sets deny on tools it
// cannot yet check (fail closed). Applies to the six tools and to host
// tools, and is enforced by the executor's gate whatever the agent does.
// NewACPAgent rejects other values. Nil caps nothing.
ToolPolicy map[string]string
// SessionFilesRoot is the executor's capabilities.session_files.root: the
// directory below which the platform mounts each session's files as
// <root>/<session id>/{uploads,skills,outputs} (ADR-0021). When set, the
// file tools of a turn whose tools run on this machine reach, besides the
// workspace, exactly these three directories of that session: read,
// glob and grep in uploads and skills (read-only) and in outputs, and
// write and edit in outputs (deliverables the platform collects). Another
// session's directories, a path below the root that is none of the three,
// a "..", and a symbolic link that leaves a directory stay refused;
// write and edit anywhere else stay confined to the workspace. The session
// id must be a single safe directory name. Absolute, or empty for
// the workspace only.
SessionFilesRoot string
// InputFiles fetches the bytes of an image the user attached (a file
// block of turn.start / turn.input; see agent_acp_images.go) when the
// platform hands the turn no tools endpoint to download it from. With it
// (or PlatformTools) and an agent that takes images (initialize
// promptCapabilities.image) the agent capability declares file_inputs and
// the harness image_inputs, and the platform then sends image input; the
// image reaches the agent as an ACP image content block. Without both, the
// platform is told the agent takes no image and refuses an image input.
InputFiles ACPInputFiles
// DisablePrewarm turns off the background prewarm of the Claude Code
// profile (see WaitPrewarm); the DSH profile has none.
DisablePrewarm bool
// HarnessID is the declared harness id (default "dsh").
HarnessID string
// Model is the model name the agent uses when the turn config has none (default Upstream.Model).
Model string
// Models are the models the host lets a turn choose (agent capability
// models), for example the models the node owner's account may use: a
// turn.start config.model must be one of their ids or the turn is refused
// (-32602, never another model), and the turn's model requests go
// upstream with that model. A model's ThinkingLevels are the reasoning
// effort values (acpReasoningEfforts: none, minimal, low, medium, high,
// xhigh, max) a turn may set with config.thinking_level, or
// DefaultThinkingLevel when it sets none; the agent sends the level as the
// request's reasoning_effort. An agent that does not take a reasoning
// effort (bma-dsh-acp before 0.2.2) gets no levels declared, so a turn
// naming one is refused rather than run without it. A model without
// levels ignores config.thinking_level. Empty: config.model and
// config.thinking_level are ignored (contract) and every turn runs on
// Model. The DSH profile only.
Models []AgentModel
// SystemPrompt is the base system prompt, with one %s for the working directory (default DefaultACPSystemPrompt).
SystemPrompt string
// MaxSessions bounds the turns running at once (default
// DefaultACPMaxSessions): a turn.start past it answers executor_busy, and an
// idle session holds no slot.
MaxSessions int64
// MaxResidentSessions bounds the sessions whose agent session and Core
// session are held, running or idle (default DefaultACPResidentSessions of the
// Core's capacity, at least MaxSessions; it must not exceed the Core's
// MaxSessions). Past it the least recently used idle session is suspended
// (ACP session/close; the agent keeps its conversation) and loaded again by
// its next turn (session/load with the executor_session_ref). A session with
// a bash command left running is not suspended.
MaxResidentSessions int
CancelGrace time.Duration
KillGrace time.Duration
OnLog func(LogEvent)
// OnInteraction, when set, is told when an approval is asked of the
// platform and when it ends (answered on any client, expired or
// withdrawn), so a local UI can show the same card under the same id and
// drop it when it is settled elsewhere. It is a view only: the answer
// still comes from the platform. It must not block.
OnInteraction func(ACPInteractionEvent)
}
ACPAgentOptions configures NewACPAgent.
type ACPInputFile ¶ added in v1.5.1
type ACPInputFile struct {
SessionID string
TurnID string
// Block is the file block as the platform sent it (FileID is set).
Block AgentInputBlock
// Metadata is the turn.start metadata of the turn.
Metadata map[string]string
}
ACPInputFile is one file block the executor must fetch the bytes of.
type ACPInputFiles ¶ added in v1.5.1
type ACPInputFiles func(ctx context.Context, file ACPInputFile) (io.ReadCloser, error)
ACPInputFiles returns the content of a file block (the caller closes it and reads at most the image limit). It sets ACPAgentOptions.InputFiles.
type ACPInteractionEvent ¶ added in v1.3.0
type ACPInteractionEvent struct {
// Phase is "requested" or "ended".
Phase string
// Kind is InteractionKindPermission (an approval; InteractionID is the
// platform interaction) or InteractionKindQuestion (ask_user_question;
// InteractionID is the agent.custom_tool_use event id the session waits on).
Kind string
SessionID string
InteractionID string
ToolName string
// ToolInput is the tool call's input (Phase "requested" only).
ToolInput map[string]any
// Outcome is the platform answer when Phase is "ended" (allow, deny,
// expired, canceled), or "withdrawn" when the turn ended first.
Outcome string
}
ACPInteractionEvent is one step of a platform interaction asked by the local agent.
type ACPModelUpstream ¶ added in v1.3.0
type ACPModelUpstream struct {
// BaseURL ends in /v1; requests go to BaseURL + "/chat/completions".
BaseURL string
// Model is the default model of a turn (ACPAgentOptions.Model defaults
// to it). A request goes upstream with the turn's model: this one, or the
// one of ACPAgentOptions.Models the turn chose.
Model string
// Header adds the credential (for example Authorization) to a forwarded request.
Header func(*http.Request)
// SessionHeader, when set, names a request header that every request
// forwarded to this endpoint carries, with the platform session id of the
// turn it belongs to (turn.start session_id) as its value, so the endpoint
// can account a request to its session. It is set before Header runs. The
// value never comes from the agent: a forwarded request is built anew and
// takes no such header from the agent's request. Requests that go to the
// platform's own model endpoint (turn.start metadata model_base_url) do
// not carry it.
SessionHeader string
}
ACPModelUpstream is where model requests go when turn.start carries no platform model endpoint: the node owner's own OpenAI-compatible endpoint.
type Ack ¶
type Ack struct {
Accepted bool `json:"accepted"`
}
Ack Generic acknowledgement returned by executor RPC methods.
func SendInteractionCancel ¶
func SendInteractionCancel(ctx context.Context, rpc RPC, params InteractionCancelParams) (Ack, error)
SendInteractionCancel calls interaction.cancel.
func SendSessionEnded ¶
SendSessionEnded calls session.ended.
func SendSessionReady ¶
SendSessionReady calls session.ready.
func SendToolResult ¶
SendToolResult calls tool.result.
type AgentCapability ¶
type AgentCapability struct {
Enabled bool `json:"enabled"`
// Models the local agent can run. An empty list means the executor picks its own model and ignores AgentTurnConfig.model.
Models []AgentModel `json:"models,omitempty"`
// Permission mode ids the local agent understands, for example default, accept_edits, plan, bypass_permissions. The executor defines the ids; the platform only passes one back in AgentTurnConfig.permission_mode.
PermissionModes []string `json:"permission_modes,omitempty"`
// Interaction kinds the executor may open with interaction.request.
InteractionKinds []string `json:"interaction_kinds,omitempty"`
// The executor resolves file input blocks (session file ids) itself.
FileInputs bool `json:"file_inputs,omitempty"`
// Turns the executor runs at once. A turn.start while that many turns are running answers -32009 executor_busy (retryable). A session with no running turn holds no slot; an executor may release the local resources of its least recently used idle sessions and load them again from executor_session_ref on the next turn.start.
MaxSessions int64 `json:"max_sessions,omitempty"`
// The executor keeps the state of its turns across a process restart. When it registers again without a session whose turn was running, the platform starts the same turn again in a new event epoch (turn.start with the same turn_id, input_id and executor_session_ref, then the turn.input the turn already received) and the executor continues the turn from its own state. Without it such a turn ends failed (session.error, session.status_idle retries_exhausted) and is not sent again: an executor without that state would run the turn again from its opening input and repeat tool calls whose effects already happened.
TurnResume bool `json:"turn_resume,omitempty"`
// Per-turn credentials the executor asks the platform to hand it in turn.start metadata: brain_tools (tools_mcp_url, tools_mcp_token: the session's tools endpoint) and harness_model (model_base_url, model_token: the session's model endpoint; optionally model_context_window and model_max_output_tokens, positive integer strings: the resolved model's context window and output ceiling, absent when the platform has no catalog entry for the model, in which case the executor uses its own defaults). A declaration only states what the executor can use; the platform decides by the executor's identity: a platform service executor gets what it declares; on a platform-managed pool machine an ACP harness turn gets harness_model by default, without a declaration; a BYO machine gets harness_model only when it declares it, and an undeclared BYO machine gets nothing, so it keeps using the model endpoint configured on it and the platform never overrides that upstream. brain_tools (contract 1.4.0) is handed to a tenant executor only when the session binds this machine as the brain machine and a different machine as the hands machine (brain and hands apart, ADR-0029) and the executor declared brain_tools; the token is bound to the org, the session, the turn, this machine and the brain epoch of the turn (the event epoch of the turn.start that carries it), so a turn started again in a new epoch gets a new token and calls made with the previous epoch's token are refused. When one machine is both brain and hands nothing is handed (the executor runs its tools itself); a platform service executor and an executor that did not declare brain_tools never get it. Until contract 1.4.0 brain_tools was never handed to a tenant executor. The harness_model token is a bma-model token bound to the turn's org, session, turn and machine (model_base_url is the machine's proxy path). Tokens are computed for each turn.start, are valid until the turn ends, and are never stored.
PlatformCredentials []string `json:"platform_credentials,omitempty"`
// The executor runs custom tools defined by the platform agent: it emits agent.custom_tool_use for a call to one and waits for agent.custom_tool_result. Without it the platform never sends agent.custom_tool_result and answers a user.custom_tool_result for the session with an error.
CustomTools bool `json:"custom_tools,omitempty"`
// Deprecated: one hosted agent. Use harnesses; an executor that sets both lists this one in harnesses too.
Harness *AgentHarnessCapability `json:"harness,omitempty"`
// Every third-party agent the executor can host, by distinct id (for example dsh and claude-code). The platform picks one per turn with AgentTurnConfig.harness; an executor declares only agents that are installed and passed their self-check.
Harnesses []AgentHarnessCapability `json:"harnesses,omitempty"`
}
AgentCapability agent capability. Present with enabled=true when the executor runs a complete agent and accepts turn.start, turn.input, turn.cancel, session.close and interaction.response (and agent.custom_tool_result when custom_tools is true).
type AgentCustomToolResultParams ¶ added in v1.3.0
type AgentCustomToolResultParams struct {
SessionID string `json:"session_id"`
// The event_id of the agent.custom_tool_use this result answers.
ToolUseID string `json:"tool_use_id"`
Content []ContentBlock `json:"content"`
// The user's application reports the call failed; the content explains why.
IsError bool `json:"is_error,omitempty"`
}
AgentCustomToolResultParams is the params object of agent.custom_tool_result.
type AgentCustomToolUseEvent ¶ added in v1.3.0
type AgentCustomToolUseEvent struct {
Type string `json:"type"`
Name string `json:"name"`
Input map[string]any `json:"input"`
}
AgentCustomToolUseEvent A custom tool the local agent is calling: a tool the user's application runs and answers (capability agent.custom_tools). Its event_id is the tool_use_id. The platform shows the session as waiting (session.status_idle with stop_reason requires_action naming the event) and delivers the user's result with agent.custom_tool_result. The turn stays open while the executor waits: the executor does not send session.status_idle for it. If its own timeout passes first, the executor ends the call with a failed agent.tool_result naming this event.
type AgentError ¶ added in v1.4.0
AgentError is an error of RunTurn that names its cause with one of the contract's AgentErrorCode values (AgentErrorCodeAgentUnavailable, AgentErrorCodeAgentAuthRequired, ...): the turn ends failed with session.error of that type, so every agent says the same thing for the same cause. Any other error ends the turn with AgentErrorCodeAgentError.
func (*AgentError) Error ¶ added in v1.4.0
func (e *AgentError) Error() string
type AgentErrorInfo ¶
type AgentErrorInfo struct {
// An AgentErrorCode value; other strings are tolerated (objects accept unknown members) and projected as unknown_error.
Type string `json:"type"`
Message string `json:"message,omitempty"`
}
AgentErrorInfo Typed session error.
type AgentEventRecord ¶
type AgentEventRecord struct {
SessionID string
TurnID string
EventID string
Sequence int64
Type string
// Event is the event object as sent, for example an AgentMessageEvent.
Event json.RawMessage
}
AgentEventRecord is one validated durable agent event.
type AgentHandler ¶
type AgentHandler interface {
// OpenTurn decides whether to accept a turn.start and reports the
// configuration the agent will actually apply. It runs before turn.start
// is answered, and the platform answers turn.start with a timeout, so it
// must be quick: refuse what can be refused for certain (unknown
// harness, a cwd outside the allowed roots) and leave anything slow, such as
// starting a process or opening the local conversation, to RunTurn, whose
// failure ends the turn with session.error (AgentError picks its type) and
// whose canceled ctx ends it canceled. An *RPCError keeps its
// code (for example -32001 for a cwd outside the allowed roots).
OpenTurn(ctx context.Context, params TurnStartParams) (TurnStartResult, error)
// RunTurn does the turn's work and returns when the turn is over. ctx is
// canceled by turn.cancel and session.close. A nil error ends the turn as
// completed, a canceled ctx as canceled, any other error as failed (the
// SDK emits session.error first).
RunTurn(ctx context.Context, turn *AgentTurn) error
// CloseSession releases the local conversation after session.close.
CloseSession(ctx context.Context, sessionID, reason string) error
}
AgentHandler is a complete local agent (model loop and tools) served over the executor protocol. The SDK owns the wire: turn.start/input/cancel, session.close, event ids and sequences, ACK tracking and resend after reconnect, interactions, and the session.status_running / status_idle events that frame every turn.
type AgentHarnessCapability ¶ added in v1.0.0
type AgentHarnessCapability struct {
// Agent profile id, for example dsh.
ID string `json:"id"`
// Installed agent package version.
Version string `json:"version"`
// Protocol the executor speaks to the agent, for example acp/1.
Protocol string `json:"protocol,omitempty"`
// Name the agent reported about itself (ACP initialize agentInfo.name).
AgentName string `json:"agent_name,omitempty"`
// Version the agent reported about itself (ACP initialize agentInfo.version); may differ from version.
AgentVersion string `json:"agent_version,omitempty"`
// token: agent.message and agent.thinking stream as deltas. committed: each message arrives whole once the agent committed it.
Streaming string `json:"streaming,omitempty"`
// A conversation continues in a new agent process (ACP session/resume).
SessionResume bool `json:"session_resume,omitempty"`
// A conversation can be reloaded with its history replayed (ACP session/load).
SessionLoad bool `json:"session_load,omitempty"`
// The agent accepts image input.
ImageInputs bool `json:"image_inputs,omitempty"`
// Which tool calls reach interaction.request. full: every call the agent's policy asks about. escalation_only: only calls that leave the agent's own sandbox; calls inside it (including workspace writes) are never asked. none: the agent never asks, so platform approval covers no tool call.
PermissionRelay string `json:"permission_relay,omitempty"`
// The agent reports typed errors; false means session.error carries agent_error with the agent's text.
StructuredErrors bool `json:"structured_errors,omitempty"`
// tokens: the agent reports token usage. context_only: it reports context window occupancy only; usage is metered by the model proxy.
Usage string `json:"usage,omitempty"`
}
AgentHarnessCapability What the third-party agent the executor hosts (for example an ACP agent) supports; an omitted boolean is false. Sent with executor.capabilities.update once the agent has started; absent until then and after a reconnect until the next turn. Informational: the platform records it and reflects it in the session harness capabilities.
type AgentInputBlock ¶
type AgentInputBlock struct {
Type string `json:"type"`
Text string `json:"text,omitempty"`
FileID string `json:"file_id,omitempty"`
Name string `json:"name,omitempty"`
MimeType string `json:"mime_type,omitempty"`
SizeBytes int64 `json:"size_bytes,omitempty"`
}
AgentInputBlock One block of user input. A file block references a platform session file by file_id; the executor downloads it through the executor files API. File bytes never travel on the control channel.
type AgentMCPToolResultEvent ¶
type AgentMCPToolResultEvent struct {
Type string `json:"type"`
MCPToolUseID string `json:"mcp_tool_use_id"`
Content []ContentBlock `json:"content,omitempty"`
IsError bool `json:"is_error,omitempty"`
}
AgentMCPToolResultEvent Result of an agent.mcp_tool_use.
type AgentMCPToolUseEvent ¶
type AgentMCPToolUseEvent struct {
Type string `json:"type"`
MCPServerName string `json:"mcp_server_name"`
Name string `json:"name"`
Input map[string]any `json:"input"`
EvaluatedPermission *EvaluatedPermission `json:"evaluated_permission,omitempty"`
}
AgentMCPToolUseEvent An MCP tool the local agent is calling. Its event_id is the mcp_tool_use_id.
type AgentMessageEvent ¶
type AgentMessageEvent struct {
Type string `json:"type"`
Content []ContentBlock `json:"content"`
}
AgentMessageEvent Final assistant text. Streaming previews for the same event_id arrive earlier as session.event_delta.
type AgentModel ¶
type AgentModel struct {
ID string `json:"id"`
DisplayName string `json:"display_name,omitempty"`
// Thinking or reasoning-effort levels the model accepts, lowest first. Use the reasoning effort values of the model APIs: none, minimal, low, medium, high, xhigh, max (OpenAI reasoning_effort; Claude Code effort levels are low, medium, high, xhigh, max). An executor that drives an OpenAI-compatible endpoint sends the level as reasoning_effort unchanged. Empty or absent: the model takes no level and AgentTurnConfig.thinking_level is not applied.
ThinkingLevels []string `json:"thinking_levels,omitempty"`
// Level applied when the turn names none; one of thinking_levels. Absent: no level is sent and the model uses its own default.
DefaultThinkingLevel string `json:"default_thinking_level,omitempty"`
}
AgentModel One model the local agent can run.
type AgentModelTokens ¶ added in v1.3.0
type AgentModelTokens interface {
RefreshModelToken(ctx context.Context, executor *Executor, params ModelTokenRefreshParams) (ModelTokenRefreshResult, error)
}
AgentModelTokens is implemented by an AgentPlatform that answers model_token.refresh: a fresh model credential for a running turn. A returned *RPCError is sent as is. Without it the method is not handled.
type AgentPlatform ¶
type AgentPlatform interface {
// AckedSequence is the highest contiguous sequence already persisted for
// the session (0 when none). The harness asks once per session per process
// so a restarted platform keeps deduplicating resent events.
AckedSequence(ctx context.Context, sessionID string) (int64, error)
// AgentEvent persists one durable event and returns once it is durable;
// only then is it acknowledged to the executor and may be published to
// clients. It is called once per event, in sequence order per session.
AgentEvent(ctx context.Context, executor *Executor, event AgentEventRecord) error
// AgentDelta relays a transient preview (Anthropic event_start /
// event_delta). Never persisted.
AgentDelta(executor *Executor, delta SessionEventDeltaParams)
// InteractionRequested opens (or, for a repeated interaction_id, returns)
// the platform interaction and returns its id. Answer it later with
// Executor.RespondInteraction.
InteractionRequested(ctx context.Context, executor *Executor, request InteractionRequestParams) (string, error)
// InteractionCanceled closes the platform interaction without an answer.
InteractionCanceled(ctx context.Context, executor *Executor, cancel InteractionCancelParams) error
}
AgentPlatform is the platform half of the agent capability: where durable agent events, previews and interactions go. BMA implements it on top of its session event log and agent interactions; tests and local tools can keep everything in memory.
type AgentSessionSuspender ¶ added in v1.5.0
type AgentSessionSuspender interface {
// MaxResidentSessions is the limit; 0 means unbounded.
MaxResidentSessions() int
// SuspendSession releases the resources of an idle session and keeps its
// conversation so that a later OpenTurn can continue it. It must be safe
// for a session the handler no longer has. An error keeps the session
// resident; the SDK then suspends the next candidate.
SuspendSession(ctx context.Context, sessionID string) error
}
AgentSessionSuspender is an optional extension of AgentHandler for a handler that holds local resources per session (a process, a conversation in memory, a Core session). The SDK counts two things apart:
- running turns, bounded by AgentCapability.MaxSessions: a turn.start that would exceed it answers executor_busy, and the slot is free again when the turn ends;
- resident sessions, bounded by MaxResidentSessions: sessions whose resources are held, running or idle. A session with no running turn costs no slot; it only keeps its resources until it is the least recently used idle one when the limit is passed.
Past the limit the SDK calls SuspendSession for the least recently used idle session before it opens the next turn. A suspended session is not ended: the platform still has it, its events keep their numbering, and its next turn.start goes to OpenTurn like any other, where the handler loads the conversation again (turn.start carries the executor_session_ref). Without this extension resident sessions are not bounded.
type AgentThinkingEvent ¶
type AgentThinkingEvent struct {
Type string `json:"type"`
Content []ContentBlock `json:"content,omitempty"`
}
AgentThinkingEvent Model thinking. content may be empty when the model only reports that it thought.
type AgentToolResultEvent ¶
type AgentToolResultEvent struct {
Type string `json:"type"`
ToolUseID string `json:"tool_use_id"`
Content []ContentBlock `json:"content,omitempty"`
IsError bool `json:"is_error,omitempty"`
}
AgentToolResultEvent Result of an agent.tool_use.
type AgentToolUseEvent ¶
type AgentToolUseEvent struct {
Type string `json:"type"`
Name string `json:"name"`
Input map[string]any `json:"input"`
EvaluatedPermission *EvaluatedPermission `json:"evaluated_permission,omitempty"`
}
AgentToolUseEvent A built-in or custom tool the local agent is calling. Its event_id is the tool_use_id.
type AgentTurn ¶
type AgentTurn struct {
// contains filtered or unexported fields
}
AgentTurn is the handle RunTurn uses to talk to the platform.
func (*AgentTurn) ApprovalID ¶ added in v1.4.0
ApprovalID is the interaction id to ask a tool call's approval under (InteractionRequestParams.InteractionID) and to present with the call (RouteCall.ApprovalID): "appr_" and 24 hex characters of sha256 over session, turn and call id (ADR-0027). It is the same after a reconnect or an executor restart, so the platform keeps one interaction per call and an approval already answered is not asked again.
func (*AgentTurn) CancelInteraction ¶
CancelInteraction withdraws an open interaction, for example after the user answered it in the local UI (InteractionCancelReasonResolvedLocally). A later interaction.response for it answers accepted=false.
func (*AgentTurn) Delta ¶
Delta streams a transient preview of the durable event eventID. It is best-effort: dropped while disconnected and never resent.
func (*AgentTurn) Emit ¶
Emit queues one durable event (one of the Agent*Event / Session*Event structs) and returns its event id. Delivery is asynchronous, ordered and at-least-once; the platform deduplicates by event id.
func (*AgentTurn) EmitWithID ¶
EmitWithID is Emit with a caller-chosen event id (from NewEventID).
func (*AgentTurn) EnvironmentInfo ¶ added in v1.4.0
func (t *AgentTurn) EnvironmentInfo() *EnvironmentInfo
EnvironmentInfo describes the hands machine when brain and hands are on different machines (turn.start config.environment_info, contract 1.4.0); nil when the tools run on this machine.
func (*AgentTurn) Inputs ¶
func (t *AgentTurn) Inputs() <-chan TurnInputParams
Inputs delivers turn.input messages in arrival order.
func (*AgentTurn) NewEventID ¶
NewEventID returns a fresh event id, for a message that is streamed with Delta before it is emitted with EmitWithID.
func (*AgentTurn) Params ¶
func (t *AgentTurn) Params() TurnStartParams
func (*AgentTurn) RefreshModelToken ¶ added in v1.3.0
func (t *AgentTurn) RefreshModelToken(ctx context.Context) (ModelTokenRefreshResult, error)
RefreshModelToken asks the platform for a fresh model credential for this turn (Client.RefreshModelToken).
func (*AgentTurn) RefreshToolsToken ¶ added in v1.4.0
func (t *AgentTurn) RefreshToolsToken(ctx context.Context) (ToolsTokenRefreshResult, error)
RefreshToolsToken asks the platform for a fresh credential for this turn's platform tool calls (Client.RefreshToolsToken).
func (*AgentTurn) RequestCustomTool ¶ added in v1.3.0
func (t *AgentTurn) RequestCustomTool(ctx context.Context, name string, input map[string]any) (string, AgentCustomToolResultParams, error)
RequestCustomTool emits agent.custom_tool_use for a tool the user's application runs (capability CustomTools) and waits for the platform's agent.custom_tool_result. It returns the call's event id with the result so the agent can reference it. The turn stays open while it waits: do not end it, and do not emit session.status_idle. When ctx ends first it returns ctx.Err() and a later result answers accepted=false; to give up on a call the agent emits a failed AgentToolResultEvent naming the returned id (empty when the event could not be emitted). Use ctx with a timeout for an executor-side limit.
func (*AgentTurn) RequestInteraction ¶
func (t *AgentTurn) RequestInteraction(ctx context.Context, params InteractionRequestParams) (InteractionResponseParams, error)
RequestInteraction asks the platform for an approval or an answer and waits for interaction.response. It flushes first so the platform already has the agent.tool_use the request references. When ctx ends or ExpiresAt passes, it withdraws the interaction with interaction.cancel; an expiry returns outcome expired, which the agent must treat as a deny. The answer is advice: the local agent still makes the final decision.
func (*AgentTurn) Tools ¶ added in v1.4.0
Tools returns the route this turn's tool calls go through when the hands are on another machine (ADR-0029), or nil when they are this machine.
A turn started with the platform's tools endpoint (turn.start metadata tools_mcp_url and tools_mcp_token, contract 1.4.0; the executor declared AgentCapability.platform_credentials brain_tools) gets a PlatformToolRoute: every call goes to the platform's tool gateway and none may run on this machine. The token stays in memory and is replaced through tools_token.refresh before it expires. One of the two metadata keys without the other gives a route that refuses every call (tools_unavailable) instead of nil, so a half credential never turns into a local run.
nil means the turn carries no tools endpoint: the brain's tools run here, on the brain's own account (ACPAgent does it through Core with its own re-checks; a brain of your own runs them itself). The route is the same value for every call of the turn.
type AgentTurnConfig ¶
type AgentTurnConfig struct {
// Model the turn runs on. When the capability lists models it must be one of models[].id: an executor answers any other with -32602 invalid params and never substitutes another model. When the capability lists no models the executor picks its own model and ignores this member; effective then reports the model it used.
Model string `json:"model,omitempty"`
// Reasoning effort of the turn: one of the thinking_levels of the turn's model (AgentModel). Absent: the model's default_thinking_level, or none. A level the model does not list answers -32602 invalid params; for a model that lists no levels the member is ignored and effective omits it.
ThinkingLevel string `json:"thinking_level,omitempty"`
// One of the capability permission_modes. Absent: the executor's default mode. turn.start metadata tool_policy, when present, refines the permission of single tools on top of the mode.
PermissionMode string `json:"permission_mode,omitempty"`
// Working directory on the executor host. The executor rejects a directory outside its allowed roots with -32001 forbidden. When turn.start metadata carries tools_mcp_* (brain and hands on different machines, contract 1.4.0) cwd is a path on the hands machine: the executor does not check it against its own allowed roots and does not create a workspace for it on this machine; the hands machine's own policy applies when a tool runs there.
Cwd string `json:"cwd,omitempty"`
// Contract 1.4.0, optional. Sent only when brain and hands are on different machines (turn.start metadata carries tools_mcp_*): describes the hands machine, so the brain can tell the model where its tools run. Omitted when brain and hands are the same machine, and absent from TurnStartResult.effective.
EnvironmentInfo *EnvironmentInfo `json:"environment_info,omitempty"`
// Extra system instructions from the platform agent definition.
System string `json:"system,omitempty"`
// Id of the hosted agent (one of the capability harnesses[].id) the turn runs on. Omitted: the executor's only harness. An id the executor does not host answers -32012 capability_unavailable.
Harness string `json:"harness,omitempty"`
}
AgentTurnConfig Requested (turn.start) or effective (TurnStartResult.effective) turn configuration. Every member is optional in a request; the executor reports the values it actually applied.
type ArtifactCapability ¶
type ArtifactCapability struct {
Upload bool `json:"upload"`
MaxBytes int64 `json:"max_bytes,omitempty"`
}
ArtifactCapability v1.1 artifact upload (POST /v1/environments/{environment_id}/artifacts; legacy alias POST /v1/executors/artifacts). Environment-scoped executors only.
type ArtifactRef ¶
type ArtifactRef struct {
ArtifactID string `json:"artifact_id"`
Name string `json:"name,omitempty"`
MimeType string `json:"mime_type"`
SizeBytes int64 `json:"size_bytes"`
// sha256:<hex> of the content.
Digest string `json:"digest"`
CreatedAt string `json:"created_at,omitempty"`
}
ArtifactRef Artifact reference returned by POST /v1/environments/{environment_id}/artifacts (legacy alias POST /v1/executors/artifacts) and listed in tool.result artifacts (v1.1 §6.5).
func NewArtifactRef ¶
func NewArtifactRef(artifactID, name, mimeType string, sizeBytes int64) ArtifactRef
NewArtifactRef builds an artifact reference for tool.result.
type BashInput ¶ added in v1.0.0
type BashInput struct {
// Shell command line.
Command string `json:"command"`
// Working directory, relative to the session workspace.
Cwd string `json:"cwd,omitempty"`
// Per-call timeout; the executor default applies when absent.
TimeoutMS int64 `json:"timeout_ms,omitempty"`
// Extra environment variables.
Env map[string]string `json:"env,omitempty"`
}
BashInput bash input: run command with a login shell.
type BashResult ¶ added in v1.0.0
type BashResult struct {
Stdout string
Stderr string
ExitCode int
// Truncated reports that the handler already cut the output short.
Truncated bool
}
BashResult is a finished command, rendered as Core renders it.
func (BashResult) Output ¶ added in v1.0.0
func (r BashResult) Output() ToolOutput
Output renders stdout and stderr (when not empty) and `exit_code: N`, as Core does. Output larger than DefaultCoreInlineResultBytes, or marked Truncated, is cut to Core's preview: half the limit of stdout, a quarter of stderr, and `exit_code: N (output truncated to fit the result; M bytes total)`.
type CallMethod ¶ added in v1.0.0
CallMethod is an executor-to-harness request with params P and result R.
type CallToolOptions ¶ added in v1.0.0
type CallToolOptions struct {
// ToolCallID is the idempotency id of the call; generated when empty.
ToolCallID string
DeadlineMS int64
Permission *ToolPermission
}
CallToolOptions are the optional fields of a typed harness tool call.
type Capabilities ¶
type Capabilities struct {
Shell *ShellCapability `json:"shell,omitempty"`
Files *FilesCapability `json:"files,omitempty"`
MCP *MCPCapability `json:"mcp,omitempty"`
Chrome bool `json:"chrome,omitempty"`
ComputerUse bool `json:"computer_use,omitempty"`
// v1 boolean or v1.1 DisplayCapability object.
Display json.RawMessage `json:"display,omitempty"`
Process *ProcessCapability `json:"process,omitempty"`
Artifacts *ArtifactCapability `json:"artifacts,omitempty"`
Terminal *TerminalCapability `json:"terminal,omitempty"`
Skills *SkillsCapability `json:"skills,omitempty"`
Workspace *WorkspaceCapability `json:"workspace,omitempty"`
Agent *AgentCapability `json:"agent,omitempty"`
SessionFiles *SessionFilesCapability `json:"session_files,omitempty"`
Fs *FsCapability `json:"fs,omitempty"`
RemoteBrain *RemoteBrainCapability `json:"remote_brain,omitempty"`
}
Capabilities Executor capability object. The server only sends a method to an executor that advertised its capability; otherwise the executor answers -32012 capability_unavailable.
type Capability ¶
type Capability struct {
// Advertise sets the capability bits on the register capabilities.
Advertise func(*Capabilities)
Methods map[string]Handler
SessionScoped bool
OnSessionEnd func(*CoreSession)
}
Capability is an extension of the core: a set of methods behind one or more capability bits. The core advertises the bits through Capabilities, routes the methods for every attached brain and, for SessionScoped capabilities, answers session_not_active (-32007) for unknown sessions and calls OnSessionEnd before a session reports session.ended.
func NewProcessCapability ¶
func NewProcessCapability(core *Core, opts ProcessOptions) Capability
NewProcessCapability serves process.start/read/write/interrupt/terminate/list and process.status (v1.1 §3) on core sessions: pipes or a PTY, bounded cursor-addressed output, idempotent starts and writes, timeouts, process group signals, and file transfers and Git credentials through opts. A session's processes are terminated when it stops.
func NewSkillInstallCapability ¶
func NewSkillInstallCapability(install SkillInstaller) (Capability, error)
NewSkillInstallCapability serves skill.install (skills.install) with install. Installs run one at a time.
type ChannelTarget ¶
type ChannelTarget struct {
Channel string // ChannelControl or ChannelMCP
SessionID string
ServerKey string
}
ChannelTarget names the channel a Dialer opens: the control channel, or the MCP channel of one session.assign mcp_servers entry (?channel=mcp&session_id=&server_key= on WebSocket transports).
type Client ¶
type Client struct {
// Tools has one typed slot per built-in tool: Tools.Bash.Handle(...).
// Capabilities shell, files and computer_use follow what is registered.
Tools Tools
// contains filtered or unexported fields
}
Client is an outbound executor client.
func (*Client) ActiveSessions ¶
ActiveSessions returns the sessions currently assigned to this executor.
func (*Client) ConnectionID ¶
ConnectionID returns the current connection id.
func (*Client) Done ¶
func (c *Client) Done() <-chan struct{}
Done is closed when the client stops for good: Stop, executor.close, a terminal close code (4004 replaced, 4003 unsupported protocol, ...), a credential rejected on reconnect, or exhausted reconnects.
func (*Client) Err ¶
Err explains Done: nil after Stop or executor.close, ErrReplaced after 4004, ErrCredentialRejected, ErrReconnectExhausted, or the terminal close error.
func (*Client) ExecutorID ¶
ExecutorID returns the id assigned by executor.register.
func (*Client) OnDrain ¶
func (c *Client) OnDrain(handler DrainHandler)
OnDrain registers the executor.drain handler.
func (*Client) OnSessionAssign ¶
func (c *Client) OnSessionAssign(handler SessionAssignHandler)
OnSessionAssign registers the session.assign handler.
func (*Client) OnSessionStop ¶
func (c *Client) OnSessionStop(handler SessionStopHandler)
OnSessionStop registers the session.stop handler.
func (*Client) OnToolCallAccept ¶
func (c *Client) OnToolCallAccept(accept func(ToolCallParams) error)
OnToolCallAccept registers a check run before a tool.call is acknowledged. An error answers the request instead (a *RPCError keeps its code, for example session_not_active or capability_unavailable) and the tool does not run.
func (*Client) OpenMCPChannel ¶
func (c *Client) OpenMCPChannel(ctx context.Context, sessionID, serverKey string) (*MCPChannel, error)
OpenMCPChannel opens the MCP channel (?channel=mcp on WebSocket transports) with a fresh executor token through Options.Dial. sessionID and serverKey identify the environment-owned MCP server from session.assign.mcp_servers.
func (*Client) RefreshModelToken ¶ added in v1.3.0
func (c *Client) RefreshModelToken(ctx context.Context, sessionID, turnID string) (ModelTokenRefreshResult, error)
RefreshModelToken asks the platform for a fresh model credential for the running turn (model_token.refresh, contract 1.3.0): call it before the turn.start model_token expires (ModelTokenRefreshResult.ExpiresAt). A turn that already ended answers an *RPCError with reason turn_inactive; a platform that cannot mint one answers forbidden or model_token_unavailable. It makes one attempt; the caller owns retry and backoff.
func (*Client) RefreshToolsToken ¶ added in v1.4.0
func (c *Client) RefreshToolsToken(ctx context.Context, sessionID, turnID string) (ToolsTokenRefreshResult, error)
RefreshToolsToken asks the platform for a fresh credential for the running turn's platform tool calls (tools_token.refresh, contract 1.4.0): call it before the turn.start tools_mcp_token expires (ToolsTokenRefreshResult.ExpiresAt). A turn that already ended, or one that was started again in a newer epoch, answers an *RPCError with reason turn_inactive or forbidden; a platform that cannot mint one answers tools_token_unavailable. It makes one attempt; the caller owns retry and backoff.
func (*Client) ReportToolResult ¶
ReportToolResult sends tool.result once per tool_call_id, retrying retryable failures (executor_busy, timeout, a disconnect) with exponential backoff across reconnects. A duplicate call for an accepted tool_call_id returns accepted without sending another frame.
func (*Client) ServeAgent ¶
func (c *Client) ServeAgent(handler AgentHandler, capability AgentCapability)
ServeAgent advertises the agent capability and routes the agent methods to handler. Call it before Start.
func (*Client) SessionContext ¶ added in v1.1.0
SessionContext returns the context of the agent session processID runs for (process.start metadata names it as agent_session_id). It needs a machine-scoped executor (ErrMachineTokenRequired). Results are cached per session; a failure is not.
func (*Client) SessionContextByID ¶ added in v1.1.0
SessionContextByID returns the context of an agent session bound to this machine, for capabilities without a process (an agent turn.start carries only the session id). Cached like SessionContext.
func (*Client) SessionEnded ¶
SessionEnded reports that every process and MCP server for the session has stopped. The session leaves ActiveSessions after the harness accepts.
func (*Client) SessionReady ¶
SessionReady reports that the executor accepted session.assign and has prepared the session. Call it after workspace and MCP setup complete.
func (*Client) Start ¶
func (c *Client) Start(ctx context.Context) (ExecutorRegisterResult, error)
Start fetches an executor token, connects, registers, and starts heartbeats. After a failed Start the client may be started again.
func (*Client) State ¶
func (c *Client) State() ConnectionState
State returns the current connection state.
func (*Client) UploadArtifact ¶
func (c *Client) UploadArtifact(ctx context.Context, sessionID, name, mimeType string, content []byte) (ArtifactRef, error)
UploadArtifact implements POST /v1/environments/{environment_id}/artifacts (v1.1 §6.5) with the current executor token. It must finish before a tool.result references the artifact; the upload is idempotent by (session, digest).
func (*Client) WaitReady ¶ added in v1.0.4
WaitReady blocks until the executor is registered and the registration stayed open for one heartbeat interval. State() is ready as soon as executor.register returns, but a machine-scoped executor that declared neither the process nor the agent capability is closed with 4002 right after that, so only WaitReady separates a usable executor from a registration that is about to be refused. It returns the error of a client that ended (Err, or ErrClientStopped after Stop) and ctx.Err() on timeout.
type CloseError ¶
CloseError is the error Read returns after the peer closed with a code.
func (*CloseError) Error ¶
func (e *CloseError) Error() string
type ComputerActionInput ¶ added in v1.0.0
type ComputerActionInput struct {
Action string `json:"action"`
// Display to act on.
Display string `json:"display,omitempty"`
}
ComputerActionInput computer_action input.
type ComputerActionRequest ¶ added in v1.3.0
type ComputerActionRequest struct {
Action string
PID, WindowID int
Coordinate *[2]float64
Start *[2]float64
Text string
Button string
ClickCount int
ScrollDir string
ScrollAmount int
}
ComputerActionRequest is a computer_action call. Coordinates are pixels of the last observation: screen pixels, or window-local ones with PID/WindowID.
type ComputerObserveInput ¶ added in v1.0.0
type ComputerObserveInput struct {
// Display to observe.
Display string `json:"display,omitempty"`
}
ComputerObserveInput computer_observe input.
type ComputerObserveRequest ¶ added in v1.3.0
type ComputerObserveRequest struct {
// PID and WindowID name one window; both zero observes the whole screen.
PID, WindowID int
}
ComputerObserveRequest is a computer_observe call.
type ComputerUseBackend ¶ added in v1.3.0
type ComputerUseBackend interface {
Observe(ctx context.Context, req ComputerObserveRequest) ([]ContentBlock, error)
Action(ctx context.Context, req ComputerActionRequest) ([]ContentBlock, error)
}
ComputerUseBackend performs computer use on the machine's interactive desktop. Results are tool result content blocks (an image block carries the screenshot as base64).
type Conn ¶
type Conn interface {
Read(ctx context.Context) ([]byte, error)
Write(ctx context.Context, frame []byte) error
// Close ends the connection with a WebSocket-style close code; the peer
// reads it as a *CloseError.
Close(code int, reason string) error
// Subprotocol is the negotiated executor protocol.
Subprotocol() string
}
Conn is one executor control connection: ordered JSON-RPC text frames in both directions. The protocol does not depend on the transport; the SDK ships WebSocket (cloud, executor dials out), a local socket (Unix domain socket carrying the same WebSocket upgrade) and an in-process pipe.
func NewWebSocketConn ¶
NewWebSocketConn wraps an accepted or dialed WebSocket as a Conn.
type ConnectionState ¶
type ConnectionState string
ConnectionState is the executor control channel state (ConnectionState* values).
type ContentBlock ¶
type ContentBlock struct {
Type string `json:"type"`
Text string `json:"text,omitempty"`
Data string `json:"data,omitempty"`
MimeType string `json:"mime_type,omitempty"`
URL string `json:"url,omitempty"`
ArtifactID string `json:"artifact_id,omitempty"`
}
ContentBlock Tool result content block. An artifact block carries artifact_id and mime_type instead of text (v1.1 §6.5).
func NewArtifactContentBlock ¶
func NewArtifactContentBlock(ref ArtifactRef) ContentBlock
NewArtifactContentBlock builds the content block that points at an artifact from inside tool.result content.
type Core ¶
type Core struct {
// contains filtered or unexported fields
}
Core is the executor's execution core ("hands"): bash with process-group cancellation, file tools, a stdio MCP supervisor, per-session cleanup and registered capabilities (process.*, terminal.*, skill.install, ...). It is independent of who drives it: Attach it to one Client per harness ("brain"), whether that is the BMA cloud or a local harness on a local socket, and every brain gets the same protocol behavior.
Isolation: sessions are keyed by (brain, session_id), so two brains may use the same session id without seeing each other; a request can only reach sessions its own brain assigned, and each session has its own workspace, processes and MCP servers. Capacity is shared: MaxSessions across brains, MaxSessionsPerBrain per brain. Bash is not a sandbox: every brain runs as the executor's OS user.
func NewCore ¶
func NewCore(opts CoreOptions) (*Core, error)
NewCore validates options and creates WorkRoot.
func (*Core) Attach ¶
Attach serves session.assign, session.stop, tool.call and every registered capability method for one brain on client. Call it before client.Start. brain names the harness ("cloud", "local", ...) and must be unique per core.
func (*Core) Capabilities ¶
func (c *Core) Capabilities() Capabilities
Capabilities is what an attached Client should advertise.
func (*Core) Close ¶
func (c *Core) Close()
Close stops every session of every brain without reporting session.ended.
func (*Core) Env ¶
Env builds a bash or process environment: baseEnv from the executor, the request env (bounded, loader and DenyEnv variables rejected), then CoreOptions.Env.
func (*Core) Register ¶
func (c *Core) Register(capability Capability) error
Register adds a capability. Call it before Attach; a method may be registered once.
type CoreOptions ¶
type CoreOptions struct {
// WorkRoot holds every session workspace: WorkRoot/<brain>/<session>.
WorkRoot string
// Workspace overrides the per-session directory (for example a machine
// executor whose sessions all share one directory, or a desktop app
// mapping a brain to a project folder). Tools are confined to it.
Workspace func(brain, sessionID string) string
// MaxSessions bounds active sessions across all attached brains;
// MaxSessionsPerBrain bounds one brain (defaults to MaxSessions). A full
// core answers session.assign with executor_busy (-32009, retryable).
MaxSessions int
MaxSessionsPerBrain int
// MaxMCPServersPerSession bounds session.assign.mcp_servers (default 4).
MaxMCPServersPerSession int
// BashTimeout applies when neither tool.call deadline_ms nor the bash
// timeout_ms is set (default 10 minutes).
BashTimeout time.Duration
// MaxOutputBytes caps each captured bash stream (default 1 MiB).
MaxOutputBytes int
// InlineResultBytes is the largest bash output returned inline (default
// 48 KiB, under the 64 KiB control frame). Larger output is uploaded as
// an artifact when UploadArtifacts is set, otherwise truncated.
InlineResultBytes int
// ComputerUse serves computer_observe and computer_action and advertises
// capabilities.computer_use (for example NewCuaDriver). Nil leaves
// computer use off: the harness then sends no computer_* tool.
ComputerUse ComputerUseBackend
// UploadArtifacts advertises the artifacts capability and offloads large
// bash results with Client.UploadArtifact. Only environment-scoped
// executors have an artifact store.
UploadArtifacts bool
// Env is set on every bash tool and process and cannot be overridden by
// a request (for example BMA_HOME).
Env map[string]string
// DenyEnv reports executor-private variables (credentials, state paths)
// that no bash tool, process or stdio MCP server may see: they are
// dropped from the inherited environment and a request setting one is
// rejected. NewCore rejects an Env entry it denies.
DenyEnv func(name string) bool
// RunAs, when set, is the OS identity every bash tool, process and stdio
// MCP server runs as, so a privileged executor (for example root) keeps
// its own credentials and state out of the workload's reach. HOME and
// USER in bash and process environments are the workload's. File tools
// (read/write/edit/glob/grep) run inside the executor and would bypass
// that boundary, so they are refused. Unix only.
RunAs *RunAs
// Launch runs before each bash tool command starts (tool.call and
// LocalToolRoute, so also ACPAgent's own tools), with the semantics of
// ProcessOptions.Launch: it may change the directory, argv and
// environment, or refuse the start; see LaunchFunc. File tools run inside
// the executor and do not call it (they stay within the session
// workspace). Nil starts commands as before.
Launch LaunchFunc
// FileAccess runs before every file tool (read, write, edit, glob, grep)
// of this machine: a tool.call and the tools of a LocalToolRoute (so also
// ACPAgent's). It gets the session, the tool, the operation (read or
// write) and the workspace-relative path, and refuses by returning an
// error: an *RPCError (NewReasonError) gives its data.reason as the
// refusal code, any other error permission_denied. A LocalToolRoute call
// is then not_forwarded with the code as Code, recorded like a result (the
// same call id is answered with it again); a tool.call fails with
// "<code>: <message>". Nothing is read or written when it refuses. A host
// uses it for read-only sessions, protected paths, revoked grants and
// stopped turns. The tools stay within the workspace with or without it.
// Nil allows every file tool call as before. See FileAccessRequest.
FileAccess FileAccessFunc
// ToolOutputDir, when set, holds the output files of the bash commands
// of a LocalToolRoute (so also ACPAgent's own tools):
// ToolOutputDir/<short hash of the session>/, created 0700 (owned by
// RunAs when set). Empty keeps them in .bma-bash/ under the turn's
// working directory. A host whose Launch sandboxes commands sets it to a
// directory outside every folder a session may write, so the executor
// writes nothing into the user's folders. The read tool of the session
// may read its own output files there. tool.call bash keeps its output
// in memory and does not use it.
ToolOutputDir string
// EndAfterToolCall marks sessions that carry exactly one tool call: the
// core ends them (session.ended "completed") after the result is
// delivered. BMA's durable selfhost queue assigns such sessions.
EndAfterToolCall func(SessionAssignParams) bool
OnLog func(LogEvent)
}
CoreOptions configures the execution core.
type CoreSession ¶
type CoreSession struct {
// contains filtered or unexported fields
}
CoreSession is one assigned session of one brain.
func (*CoreSession) Assignment ¶
func (s *CoreSession) Assignment() SessionAssignParams
Assignment is the session.assign that created the session.
func (*CoreSession) Brain ¶
func (s *CoreSession) Brain() string
func (*CoreSession) Client ¶
func (s *CoreSession) Client() *Client
func (*CoreSession) Context ¶
func (s *CoreSession) Context() context.Context
Context is canceled when the session stops.
func (*CoreSession) ID ¶
func (s *CoreSession) ID() string
func (*CoreSession) ResolveCwd ¶
func (s *CoreSession) ResolveCwd(cwd string) (string, error)
ResolveCwd returns the real directory for a working directory request: a relative cwd is under the workspace, an absolute one must resolve (through symlinks) under it. An absolute cwd that is exactly the executor work root (what a machine's configured cwd is, for example C:\bma\work) is the session's workspace, since the work root holds every session's workspace and is no place to run a command.
func (*CoreSession) Value ¶
func (s *CoreSession) Value(key any, create func() any) any
Value returns the per-session value for key, creating it with create on first use. Capabilities keep their session state here.
func (*CoreSession) Workspace ¶
func (s *CoreSession) Workspace() string
type CuaDriver ¶ added in v1.3.0
type CuaDriver struct {
// contains filtered or unexported fields
}
CuaDriver is the ComputerUseBackend on Cua Driver (https://github.com/trycua/cua, MIT; only the MIT driver is used, not its AGPL perception extension or its FSL space daemon): every call is `cua-driver call <tool> <json>` against the driver daemon that runs in the interactive session (Windows: a logon scheduled task, `cua-driver autostart enable`). The executor itself may run in session 0 or session 1; the daemon owns the desktop. Input is delivered in the background when a window is named; screenshots and the accessibility tree come from the same daemon.
func NewCuaDriver ¶ added in v1.3.0
func NewCuaDriver(ctx context.Context, opts CuaDriverOptions) (*CuaDriver, error)
NewCuaDriver checks that the driver and its daemon work (a screen-size call) and returns the backend, or an error wrapping ErrComputerUseUnavailable.
func (*CuaDriver) Action ¶ added in v1.3.0
func (d *CuaDriver) Action(ctx context.Context, req ComputerActionRequest) ([]ContentBlock, error)
Action performs one computer_action and returns the driver's summary.
func (*CuaDriver) Observe ¶ added in v1.3.0
func (d *CuaDriver) Observe(ctx context.Context, req ComputerObserveRequest) ([]ContentBlock, error)
Observe returns a screenshot with a text description: the screen size and the window list, or one window's accessibility tree (UIA on Windows).
type CuaDriverOptions ¶ added in v1.3.0
type CuaDriverOptions struct {
// Path is the cua-driver executable (default: cua-driver on PATH).
Path string
// Socket overrides the daemon's socket or named pipe (default: the
// driver's own, \\.\pipe\cua-driver on Windows).
Socket string
// Env is added to the driver's environment (CUA_TELEMETRY=0 is always set).
Env []string
// Timeout bounds one driver call (default 30 s).
Timeout time.Duration
}
CuaDriverOptions configures NewCuaDriver.
type CustomToolResultResult ¶ added in v1.3.0
type CustomToolResultResult struct {
Accepted bool `json:"accepted"`
}
CustomToolResultResult agent.custom_tool_result result. accepted=true: the executor took the result for the call it was waiting on. accepted=false: it no longer waits (unknown tool_use_id, already answered, timed out, or canceled with its turn); the platform marks its copy stale and does not send it again.
type DaemonHTTPError ¶ added in v1.1.0
type DaemonHTTPError struct {
StatusCode int
// Code and Message are BMA's error body when it sent one.
Code string
Message string
}
DaemonHTTPError is a non-2xx answer of a BMA daemon route.
func (*DaemonHTTPError) Error ¶ added in v1.1.0
func (e *DaemonHTTPError) Error() string
type Dialer ¶
type Dialer func(ctx context.Context, token ExecutorTokenResponse, protocol string, target ChannelTarget) (Conn, error)
Dialer opens an executor channel after the token source returned token. The default dials token.WSURL over WebSocket: ws://, wss:// or unix:///path/to.sock or npipe:////./pipe/<name> (the same WebSocket upgrade on a Unix domain socket or a Windows named pipe, as in the TypeScript and Python SDKs).
func InProcessDialer ¶
InProcessDialer connects the executor to h in the same process: every dial creates a fresh Pipe and serves its harness end with principal, as the control channel or as an MCP channel.
func ListenNamedPipe ¶
ListenNamedPipe is ListenUnixSocket on a Windows named pipe \\.\pipe\<name>: the executor listens and the next local harness that dials it with Authorization: Bearer token (Harness.DialExecutor with the pipe name or an npipe:// URL) becomes its brain.
func ListenUnixSocket ¶
ListenUnixSocket makes the executor the listening side on a local machine: it creates a 0700 directory and a 0600 Unix socket at path and returns a Dialer that waits for the next local harness ("brain") to connect with Authorization: Bearer token. The roles do not change: the brain is still the harness and the executor still registers. The brain (Harness. DialExecutor) also dials the MCP channels of its sessions; an MCP dial waits for that connection. Use it as Options.Dial with TokenSource StaticToken("ws://local/", "") so the executor reconnects by accepting again. Close the returned closer to stop listening.
func NamedPipeDialer ¶
NamedPipeDialer dials a harness serving Harness.ServeHTTP on the Windows named pipe \\.\pipe\<name> (NamedPipeListener). token.WSURL is ignored; StaticToken("npipe:////./pipe/"+name, token) with the default dialer is equivalent.
func UnixSocketDialer ¶
UnixSocketDialer dials a harness listening on the Unix domain socket at path (the harness serves Harness.ServeHTTP on that listener). token.WSURL is ignored; StaticToken("unix://"+path, token) with the default dialer is equivalent.
func WebSocketDialer ¶
WebSocketDialer dials token.WSURL (ws://, wss://, unix:// or npipe://) with the bearer token in the Authorization header. httpClient may carry a proxy or a custom transport; nil uses http.DefaultClient. A unix:// URL always dials its socket.
type DisplayCapability ¶
type DisplayCapability struct {
RFB bool `json:"rfb,omitempty"`
// The machine can host its own desktop for a desktop session (it carries bma-desktop-session, started through process.start). Absent means unknown (an executor that predates the field).
Desktop bool `json:"desktop,omitempty"`
}
DisplayCapability v1.1 display object. v1 sent a boolean; the server accepts both.
type DrainHandler ¶
type DrainHandler func(ctx context.Context, params ExecutorDrainParams) (ExecutorDrainResult, error)
DrainHandler handles an inbound executor.drain.
type EditInput ¶ added in v1.0.0
type EditInput struct {
// File path, relative to the session workspace.
Path string `json:"path"`
// Text that must occur exactly once.
OldString string `json:"old_string"`
// Replacement text.
NewString string `json:"new_string"`
}
EditInput edit input: replace the single occurrence of old_string.
type EnvironmentInfo ¶ added in v1.3.0
type EnvironmentInfo struct {
// Operating system of the hands machine, as ExecutorInfo.os (for example linux, darwin, windows).
OS string `json:"os,omitempty"`
// CPU architecture, as ExecutorInfo.arch.
Arch string `json:"arch,omitempty"`
// Shell the bash tool runs commands with on the hands machine (for example bash, zsh, powershell).
Shell string `json:"shell,omitempty"`
// Default working directory of tools on the hands machine; the same value as AgentTurnConfig.cwd when that is set.
Cwd string `json:"cwd,omitempty"`
// Directory on the hands machine where the session's files are mounted, when the hands executor declared session_files.
SessionFilesRoot string `json:"session_files_root,omitempty"`
}
EnvironmentInfo Contract 1.4.0. The hands machine as the platform knows it (AgentTurnConfig.environment_info), from the hands executor's registration and the session's file mounts. Every member is optional; an omitted member is unknown, not empty. Values describe the machine at the time of turn.start.
type EvaluatedPermission ¶
type EvaluatedPermission struct {
Type string `json:"type"`
}
EvaluatedPermission Permission decision the executor applied to a tool use. ask means the executor opened an interaction.request for it.
type Executor ¶
type Executor struct {
// contains filtered or unexported fields
}
Executor is one registered executor. It outlives a single connection: a reconnect with resume.executor_id within the lease attaches to the same Executor and keeps its sessions and pending tool calls.
func (*Executor) AgentCapability ¶
func (e *Executor) AgentCapability() (*AgentCapability, error)
AgentCapability returns the advertised agent capability, nil when absent.
func (*Executor) AssignSession ¶
AssignSession binds a session to this executor and sends session.assign. WorkID and the lease token are generated when empty. The session is bound before the request is sent, so session.ready and MCP channels that race the assign response are accepted.
func (*Executor) Call ¶
Call sends a harness-to-executor request for a capability method (process.*, terminal.*, skill.install, ...) and decodes its result. A JSON-RPC error answer is an *RPCError.
func (*Executor) CancelTurn ¶
func (e *Executor) CancelTurn(ctx context.Context, params TurnCancelParams) (TurnCancelResult, error)
CancelTurn sends turn.cancel. The turn's end is still reported by its session.status_idle event.
func (*Executor) Capabilities ¶
Capabilities decodes the advertised capabilities into out (for example *Capabilities, or a v1.1 capability struct).
func (*Executor) CloseAgentSession ¶
func (e *Executor) CloseAgentSession(ctx context.Context, params SessionCloseParams) (SessionCloseResult, error)
CloseAgentSession sends session.close.
func (*Executor) Drain ¶
Drain asks the executor to stop accepting sessions; existing sessions run to completion. Heartbeats report drain=true from now on.
func (*Executor) Info ¶
func (e *Executor) Info() ExecutorInfo
func (*Executor) RespondCustomToolResult ¶ added in v1.3.0
func (e *Executor) RespondCustomToolResult(ctx context.Context, params AgentCustomToolResultParams) (CustomToolResultResult, error)
RespondCustomToolResult delivers the user's result for an agent.custom_tool_use. accepted=false means the executor no longer waits (unknown tool_use_id, answered already, timed out, or canceled with its turn); mark the platform's copy stale and do not send it again.
func (*Executor) RespondInteraction ¶
func (e *Executor) RespondInteraction(ctx context.Context, params InteractionResponseParams) (InteractionResponseResult, error)
RespondInteraction delivers the platform's answer. accepted=false means the executor no longer waits for it (answered already, withdrawn, or unknown); mark the platform interaction stale.
func (*Executor) SendTurnInput ¶
SendTurnInput sends turn.input; a conflict means the turn is over and the input belongs in a new turn.start.
func (*Executor) StartTurn ¶
func (e *Executor) StartTurn(ctx context.Context, params TurnStartParams) (TurnStartResult, error)
StartTurn sends turn.start. It is safe to repeat with the same turn_id after a timeout or reconnect.
type ExecutorCapabilitiesUpdateParams ¶
type ExecutorCapabilitiesUpdateParams struct {
Capabilities Capabilities `json:"capabilities"`
}
ExecutorCapabilitiesUpdateParams is the params object of executor.capabilities.update.
type ExecutorCloseParams ¶
type ExecutorCloseParams struct {
Reason string `json:"reason"`
}
ExecutorCloseParams is the params object of executor.close.
type ExecutorDrainParams ¶
type ExecutorDrainParams struct {
Reason string `json:"reason"`
DeadlineMS int64 `json:"deadline_ms,omitempty"`
}
ExecutorDrainParams is the params object of executor.drain.
type ExecutorDrainResult ¶
type ExecutorDrainResult struct {
Accepted bool `json:"accepted"`
ActiveSessions []string `json:"active_sessions"`
}
ExecutorDrainResult executor.drain result.
type ExecutorHeartbeatParams ¶
type ExecutorHeartbeatParams struct {
ConnectionID string `json:"connection_id"`
ActiveSessions []string `json:"active_sessions"`
Load *ExecutorLoad `json:"load,omitempty"`
}
ExecutorHeartbeatParams is the params object of executor.heartbeat.
type ExecutorHeartbeatResult ¶
type ExecutorHeartbeatResult struct {
ServerTime string `json:"server_time"`
LeaseTTLMS int64 `json:"lease_ttl_ms"`
Drain bool `json:"drain"`
}
ExecutorHeartbeatResult executor.heartbeat result.
func SendExecutorHeartbeat ¶
func SendExecutorHeartbeat(ctx context.Context, rpc RPC, params ExecutorHeartbeatParams) (ExecutorHeartbeatResult, error)
SendExecutorHeartbeat calls executor.heartbeat.
type ExecutorInfo ¶
type ExecutorInfo struct {
Name string `json:"name"`
OS string `json:"os"`
Arch string `json:"arch"`
Version string `json:"version"`
// Contract 1.4.0, optional. Labels the executor reports about itself (at most 32, each 1-64 characters of a-z 0-9 . _ -), set by the machine's owner in the executor's local configuration (for example BMA_LABELS or the SDK Options.Labels). The platform accepts them as given and does not validate their meaning, and it adds its own os:<os> and arch:<arch> labels from os and arch. Labels only narrow a choice among machines the project is already authorized to use (environment placement selectors); no authorization or security decision depends on them. Omitted: no labels.
Labels []string `json:"labels,omitempty"`
}
ExecutorInfo Executor identity reported at token bootstrap and registration.
type ExecutorLoad ¶
type ExecutorLoad struct {
CPUPercent float64 `json:"cpu_percent,omitempty"`
MemoryPercent float64 `json:"memory_percent,omitempty"`
}
ExecutorLoad Advisory executor load reported with executor.heartbeat. The server does not act on it.
type ExecutorRegisterParams ¶
type ExecutorRegisterParams struct {
Protocol string `json:"protocol"`
// Selfhost environment id; empty for a machine-scoped executor.
EnvironmentID string `json:"environment_id"`
Executor ExecutorInfo `json:"executor"`
Capabilities Capabilities `json:"capabilities"`
Resume *ExecutorResume `json:"resume,omitempty"`
}
ExecutorRegisterParams is the params object of executor.register.
type ExecutorRegisterResult ¶
type ExecutorRegisterResult struct {
ExecutorID string `json:"executor_id"`
ConnectionID string `json:"connection_id"`
ServerTime string `json:"server_time"`
HeartbeatIntervalMS int64 `json:"heartbeat_interval_ms"`
LeaseTTLMS int64 `json:"lease_ttl_ms"`
MaxControlFrameBytes int64 `json:"max_control_frame_bytes"`
MaxMCPFrameBytes int64 `json:"max_mcp_frame_bytes"`
Drain bool `json:"drain"`
Protocol string `json:"protocol,omitempty"`
Limits *Limits `json:"limits,omitempty"`
}
ExecutorRegisterResult executor.register result. protocol and limits are v1.1 only.
func SendExecutorRegister ¶
func SendExecutorRegister(ctx context.Context, rpc RPC, params ExecutorRegisterParams) (ExecutorRegisterResult, error)
SendExecutorRegister calls executor.register.
type ExecutorResume ¶
type ExecutorResume struct {
ExecutorID string `json:"executor_id,omitempty"`
LastConnectionID string `json:"last_connection_id,omitempty"`
ActiveSessions []string `json:"active_sessions,omitempty"`
}
ExecutorResume Reattach state sent on reconnect.
type ExecutorTokenRefreshParams ¶
type ExecutorTokenRefreshParams struct {
Token string `json:"token"`
}
ExecutorTokenRefreshParams is the params object of executor.token.refresh.
type ExecutorTokenRefreshResult ¶
type ExecutorTokenRefreshResult struct {
// RFC 3339 time of the new connection deadline.
ExpiresAt string `json:"expires_at"`
}
ExecutorTokenRefreshResult executor.token.refresh result: the connection now closes with 4001 at expires_at.
func SendExecutorTokenRefresh ¶
func SendExecutorTokenRefresh(ctx context.Context, rpc RPC, params ExecutorTokenRefreshParams) (ExecutorTokenRefreshResult, error)
SendExecutorTokenRefresh calls executor.token.refresh.
type ExecutorTokenRequest ¶
type ExecutorTokenRequest struct {
EnvironmentID string `json:"environment_id"`
Executor ExecutorInfo `json:"executor"`
}
ExecutorTokenRequest Token request body for POST /v1/machines/{machine_id}/token (bearer: machine daemon token) and POST /v1/environments/{environment_id}/token (bearer: environment key); the legacy alias POST /v1/executors/token takes either bearer. The id in the path must equal the credential's machine or environment, otherwise 404; on the new paths environment_id may be empty or absent for a machine and, when sent for an environment, must equal the path id. An empty environment_id with a machine token requests a machine-scoped executor: its executor_id is exec_<machine_id>, stable across refreshes, and the JWT carries machine_id and daemon_token_id.
type ExecutorTokenResponse ¶
type ExecutorTokenResponse struct {
ExecutorID string `json:"executor_id"`
// Short-lived executor JWT, sent only in the Authorization header of the channel upgrade.
Token string `json:"token"`
// Seconds.
ExpiresIn int64 `json:"expires_in"`
WSURL string `json:"ws_url"`
ChannelScope []string `json:"channel_scope"`
}
ExecutorTokenResponse Token response of POST /v1/machines/{machine_id}/token, POST /v1/environments/{environment_id}/token and the legacy alias POST /v1/executors/token.
type FileAccessFunc ¶ added in v1.4.0
type FileAccessFunc func(ctx context.Context, req FileAccessRequest) error
FileAccessFunc is CoreOptions.FileAccess.
type FileAccessRequest ¶ added in v1.4.0
type FileAccessRequest struct {
// SessionID is the executor's session id. AgentSessionID is the agent
// session: for a LocalToolRoute the same id, for a tool.call the
// session.assign metadata agent_session_id (empty when it has none).
SessionID, AgentSessionID string
// Tool is read, write, edit, glob or grep; ToolCallID the call.
Tool, ToolCallID string
// Operation is FileOperationRead or FileOperationWrite. read, glob and
// grep read; write writes; edit reads and writes, so the hook is called
// twice for it, read first. glob and grep are asked about their search
// directory, not about each file under it.
Operation string
// Path is the file or directory, relative to the session workspace,
// cleaned and slash-separated ("." is the workspace itself); when Mount
// is set it is relative to that mount's directory instead. A call whose
// path is outside the workspace and the session's mounts fails without
// asking the hook.
Path string
// Mount names the session's mounted directory Path is in: "uploads",
// "skills" or "outputs" (see ACPAgentOptions.SessionFilesRoot). Empty for
// the workspace. A hook that guards the workspace only should treat a
// request with a Mount as outside its scope or check it explicitly.
Mount string
}
FileAccessRequest is what CoreOptions.FileAccess is asked before a file tool runs.
type FileTransferError ¶
type FileTransferError struct {
Code string `json:"code"`
Message string `json:"error"`
CurrentDigest string `json:"current_digest,omitempty"`
}
FileTransferError Failed file transfer.
type FileTransferResult ¶
type FileTransferResult struct {
Path string `json:"path,omitempty"`
Digest string `json:"digest,omitempty"`
Error *FileTransferError `json:"error,omitempty"`
}
FileTransferResult Ended file transfer outcome: the uploaded path and digest, the downloaded digest, or an error.
type FileTransferer ¶
type FileTransferer interface {
TransferFile(ctx context.Context, processID string, transfer ProcessFileTransfer) (FileTransferResult, error)
}
FileTransferer moves one file for a process.start file_transfer. A failure is returned both as the error (the process output, exit code 1) and as FileTransferResult.Error, which the harness reports.
type FilesCapability ¶
type FilesCapability struct {
Enabled bool `json:"enabled"`
ReadRoots []string `json:"read_roots,omitempty"`
WriteRoots []string `json:"write_roots,omitempty"`
}
FilesCapability v1 file tools.
type FsCapability ¶ added in v1.2.0
type FsCapability struct {
Fuse bool `json:"fuse"`
Views []string `json:"views,omitempty"`
// Contract 1.4.0. The executor mounts the skills view at the path of each fs.mount, whatever it is, and keeps the views of several sessions mounted at once: mounting or unmounting one session never touches another session's views. When true and the executor also declared session_files.root, the harness mounts a session's skills at <root>/<agent_session_id>/skills (next to its uploads and outputs), so sessions sharing a machine each see their own skills; the executor removes the mount points it created when the session is unmounted. Absent or false (every executor before 1.4.0): the harness mounts skills at the fixed /mnt/skills, which shows one session at a time.
SkillsPerSession bool `json:"skills_per_session,omitempty"`
}
FsCapability Session file views mounted by the executor as FUSE file systems backed by bma-file (docs/adr/0021). Declared only after the executor probed that it can mount. Absent or fuse=false: the session files stay on the copy-and-scan protocol (session_files). views lists the views the executor can mount; the harness only mounts those. Machine-scoped executors only.
type FsMount ¶ added in v1.2.0
type FsMount struct {
// uploads, skills. Open enum: outputs and memory follow.
View string `json:"view"`
Path string `json:"path"`
Readonly bool `json:"readonly"`
Token string `json:"token"`
// Reserved mount tuning (string values); unknown keys are ignored.
Options map[string]string `json:"options,omitempty"`
}
FsMount One view to mount. path is the absolute mount point on the executor host (derived from session_files by the harness; the skills view is at <root>/<agent_session_id>/skills for an executor that declared fs.skills_per_session and a root, otherwise /mnt/skills). Mount points of different sessions never overlap, and the executor mounts exactly the path it is given. readonly is also fixed inside token; the executor mounts read-only when it is true. token is a capability token for this session and machine: keep it in memory only, never write it to disk, argv, environment or logs.
type FsMountParams ¶ added in v1.2.0
type FsMountParams struct {
SessionID string `json:"session_id"`
// Complete prefix of the bma-file routes for this machine, ending in /v1/machines/{machine_id}/fs (for example https://executor.example.com/v1/machines/mach_01/fs). The executor appends "/<op>" and nothing else; it does not compose the machine id itself.
ServiceURL string `json:"service_url"`
Mounts []FsMount `json:"mounts"`
}
FsMountParams is the params object of fs.mount.
type FsMountResult ¶ added in v1.2.0
type FsMountResult struct {
State string `json:"state"`
ErrorCode string `json:"error_code,omitempty"`
Error string `json:"error,omitempty"`
}
FsMountResult fs.mount result. state is "mounted" once every listed view is mounted and serving, or "failed" with error_code and error (nothing stays half-mounted).
type FsUnmountParams ¶ added in v1.2.0
type FsUnmountParams struct {
SessionID string `json:"session_id"`
Flush bool `json:"flush,omitempty"`
}
FsUnmountParams is the params object of fs.unmount.
type FsUnmountResult ¶ added in v1.2.0
type FsUnmountResult struct {
State string `json:"state"`
PendingBytes int64 `json:"pending_bytes"`
ErrorCode string `json:"error_code,omitempty"`
Error string `json:"error,omitempty"`
}
FsUnmountResult fs.unmount result. pending_bytes is data not yet committed to bma-file when flush was requested (always 0 for read-only views).
type GitCredentialGranter ¶
type GitCredentialGranter interface {
Grant(processID string, env []string) ([]string, func(), error)
}
GitCredentialGranter backs process.start git_credentials: Grant returns the environment that lets processID fetch Git credentials while it runs, and a release function called when the process ends.
type GlobInput ¶ added in v1.0.0
type GlobInput struct {
// Glob pattern.
Pattern string `json:"pattern"`
// Base directory, relative to the session workspace.
Path string `json:"path,omitempty"`
}
GlobInput glob input: list paths matching pattern.
type GrepInput ¶ added in v1.0.0
type GrepInput struct {
// Regular expression.
Pattern string `json:"pattern"`
// Directory to search, relative to the session workspace.
Path string `json:"path,omitempty"`
// File name filter.
Glob string `json:"glob,omitempty"`
}
GrepInput grep input: search file lines with a regular expression.
type Handler ¶
Handler serves one harness-to-executor request method registered by a Capability. A *RPCError result is sent as is; any other error becomes internal_error.
type Harness ¶
type Harness struct {
// contains filtered or unexported fields
}
Harness is the harness ("brain") end of the executor protocol: an http.Handler that accepts executor control and MCP channels, plus the session.assign / tool.call / tool.cancel / session.stop API that drives them. It is the same protocol the BMA service speaks, so an executor built on this SDK cannot tell a local harness from the cloud.
func NewHarness ¶
func NewHarness(opts HarnessOptions) *Harness
NewHarness returns a harness with defaults applied.
func (*Harness) DialExecutor ¶
DialExecutor connects this harness to an executor that listens on the local Unix socket at path (ListenUnixSocket) or Windows named pipe (ListenNamedPipe; path is \\.\pipe\<name> or an npipe:// URL) and serves the connection until it closes. A local brain uses it to drive the hand already running on the machine instead of starting another one.
func (*Harness) Executors ¶
Executors returns the executors currently registered (connected or within their reconnect lease).
func (*Harness) ServeConn ¶
ServeConn serves one executor control connection on any transport (an in-process Pipe end, a dialed local socket, ...) until it closes. The caller authenticated the peer; principal pins its identity.
type HarnessMCPChannel ¶
type HarnessMCPChannel struct {
// contains filtered or unexported fields
}
HarnessMCPChannel is the harness end of one MCP channel, isolated by (session_id, server_key), on any transport. Frames are raw MCP JSON-RPC exactly as the MCP server sent them: the harness is the MCP client.
func (*HarnessMCPChannel) Close ¶
func (m *HarnessMCPChannel) Close() error
type HarnessOptions ¶
type HarnessOptions struct {
// Authenticate verifies every WebSocket upgrade (control and MCP). nil
// accepts every connection: use that only on a loopback listener.
Authenticate func(r *http.Request) (Principal, error)
// HeartbeatInterval and LeaseTTL are returned by executor.register. A
// disconnected executor keeps its sessions and pending tool calls for
// LeaseTTL; then they end and pending calls fail with
// ErrToolOutcomeUnknown.
HeartbeatInterval time.Duration
LeaseTTL time.Duration
// RequestTimeout bounds harness-to-executor requests. Defaults to 30s.
RequestTimeout time.Duration
// Protocols are the accepted subprotocols in preference order. Defaults
// to ProtocolV11 then ProtocolV1.
Protocols []string
// OnExecutor runs after each successful executor.register.
OnExecutor func(*Executor)
// OnSessionEvent persists session.event. nil accepts with a generated id.
// The harness answers a retried JSON-RPC id with the first result.
OnSessionEvent func(ctx context.Context, executor *Executor, params SessionEventParams) (SessionEventResult, error)
OnSessionStatus func(executor *Executor, params SessionStatusParams)
OnToolProgress func(executor *Executor, params ToolProgressParams)
// OnProcessStatus receives the advisory process.status notification.
OnProcessStatus func(executor *Executor, params ProcessStatusParams)
OnLog func(LogEvent)
// Agent receives agent-capability traffic: agent session events,
// previews and interactions. nil rejects them as unknown methods.
Agent AgentPlatform
}
HarnessOptions configures a Harness.
type HarnessToolSlot ¶ added in v1.0.0
type HarnessToolSlot[In any] struct { // contains filtered or unexported fields }
HarnessToolSlot calls one built-in tool from the harness end.
func (HarnessToolSlot[In]) Call ¶ added in v1.0.0
func (s HarnessToolSlot[In]) Call(ctx context.Context, input In, options CallToolOptions) (ToolResultParams, error)
Call sends tool.call with a typed input and waits for tool.result, as Session.CallTool.
type HarnessTools ¶ added in v1.0.0
type HarnessTools struct {
Bash HarnessToolSlot[BashInput]
Read HarnessToolSlot[ReadInput]
Write HarnessToolSlot[WriteInput]
Edit HarnessToolSlot[EditInput]
Glob HarnessToolSlot[GlobInput]
Grep HarnessToolSlot[GrepInput]
ListFiles HarnessToolSlot[ListFilesInput]
}
HarnessTools has one typed entry per built-in tool: session.Tools.Bash.Call(...). computer_observe and computer_action have none until the contract defines their input members.
type InteractionCancelParams ¶
type InteractionCancelParams struct {
SessionID string `json:"session_id"`
InteractionID string `json:"interaction_id"`
Reason string `json:"reason"`
}
InteractionCancelParams is the params object of interaction.cancel.
type InteractionQuestion ¶
type InteractionQuestion struct {
Prompt string `json:"prompt"`
Options []InteractionQuestionOption `json:"options,omitempty"`
MultiSelect bool `json:"multi_select,omitempty"`
AllowFreeText bool `json:"allow_free_text,omitempty"`
}
InteractionQuestion Question shown to the user.
type InteractionQuestionOption ¶
InteractionQuestionOption One answer option of a question interaction.
type InteractionRequestParams ¶
type InteractionRequestParams struct {
SessionID string `json:"session_id"`
TurnID string `json:"turn_id"`
// Executor-assigned, unique within the session and stable for the same tool call or question across executor and brain restarts (derive it from the session, the turn and the call, for example appr_ + the first 24 hex chars of sha256(session_id, NUL, turn_id, NUL, call_id); the turn is part of it because some providers reuse call ids such as call_0 in every turn), so a restarted executor asks again with the same id and gets the same platform interaction, and an answer given while it was offline, back. The platform interaction is the one card every client of the session shows; a local UI shows the same interaction rather than a separate local prompt.
InteractionID string `json:"interaction_id"`
Kind string `json:"kind"`
// Required for permission.
ToolUseID string `json:"tool_use_id,omitempty"`
ToolName string `json:"tool_name,omitempty"`
ToolInput map[string]any `json:"tool_input,omitempty"`
// Grant scopes the user may pick for permission; defaults to once.
Scopes []string `json:"scopes,omitempty"`
// Required for question.
Question *InteractionQuestion `json:"question,omitempty"`
// RFC 3339 time after which the executor stops waiting.
ExpiresAt string `json:"expires_at,omitempty"`
}
InteractionRequestParams is the params object of interaction.request.
type InteractionRequestResult ¶
type InteractionRequestResult struct {
Accepted bool `json:"accepted"`
PlatformInteractionID string `json:"platform_interaction_id"`
}
InteractionRequestResult interaction.request result. Idempotent by interaction_id: a repeat returns the same platform interaction. platform_interaction_id equals interaction_id when that is an appr_ plus 24 lower-case hex id (adopted); otherwise it is the platform-assigned int_ id.
func SendInteractionRequest ¶
func SendInteractionRequest(ctx context.Context, rpc RPC, params InteractionRequestParams) (InteractionRequestResult, error)
SendInteractionRequest calls interaction.request.
type InteractionResponder ¶
type InteractionResponder struct {
ActorID string `json:"actor_id,omitempty"`
Surface string `json:"surface,omitempty"`
}
InteractionResponder Who answered, for local audit. surface is the client that resolved it, for example desktop, mobile, web, slack.
type InteractionResponseParams ¶
type InteractionResponseParams struct {
SessionID string `json:"session_id"`
InteractionID string `json:"interaction_id"`
Outcome string `json:"outcome"`
// Granted scope for allow.
Scope string `json:"scope,omitempty"`
DenyMessage string `json:"deny_message,omitempty"`
// Selected option ids or free text for answered.
Answers []string `json:"answers,omitempty"`
Responder *InteractionResponder `json:"responder,omitempty"`
}
InteractionResponseParams is the params object of interaction.response.
type InteractionResponseResult ¶
type InteractionResponseResult struct {
Accepted bool `json:"accepted"`
}
InteractionResponseResult interaction.response result. accepted=false when the interaction is unknown or already resolved (first answer wins); the platform then marks its copy stale.
type JSONRPCError ¶
type JSONRPCError struct {
Code int `json:"code"`
Message string `json:"message"`
Data *JSONRPCErrorData `json:"data,omitempty"`
}
JSONRPCError JSON-RPC 2.0 error object.
type JSONRPCErrorData ¶
type JSONRPCErrorData struct {
// Capacity or timeout failure the caller should retry with backoff.
Retryable bool `json:"retryable,omitempty"`
Detail string `json:"detail,omitempty"`
// Missing capability for -32012, for example "tool:read" or "process.pty".
Capability string `json:"capability,omitempty"`
// Machine-readable cause; an open set that the harness passes through unchanged (process.start: the tool result error_code and the process state reason; turn.start: the session.error code). Recommended values: workspace_unavailable, workspace_boundary, workspace_read_only, session_rejected, local_confirmation_denied, local_confirmation_expired, spawn_failed / process_id_spec_mismatch for process.start, capability_missing for executor.register, and turn_inactive / forbidden / model_token_unavailable for model_token.refresh and turn_inactive / forbidden / tools_token_unavailable for tools_token.refresh (contract 1.4.0). The tool result error_code of a platform tool call (the platform tools endpoint, ToolErrorCode in the AsyncAPI x-bma-platform-tools) is an open set that also includes environment_unavailable, permission_denied, approval_required, approval_invalid, in_progress and idempotency_key_reused (contract 1.4.0). Receivers must accept values they do not know.
Reason string `json:"reason,omitempty"`
// bma.terminal.v1 error code for a failed terminal.* call.
TerminalCode string `json:"terminal_code,omitempty"`
// Agent session.event gap (-32013): the sequence the harness expects next.
ExpectedSequence int64 `json:"expected_sequence,omitempty"`
}
JSONRPCErrorData JSON-RPC error.data. Members are code-specific; unknown members are ignored.
type JSONRPCErrorResponse ¶
type JSONRPCErrorResponse struct {
JSONRPC string `json:"jsonrpc"`
ID string `json:"id"`
Error JSONRPCError `json:"error"`
}
JSONRPCErrorResponse JSON-RPC 2.0 error response envelope.
type JSONRPCNotification ¶
type JSONRPCNotification struct {
JSONRPC string `json:"jsonrpc"`
Method string `json:"method"`
Params json.RawMessage `json:"params"`
}
JSONRPCNotification JSON-RPC 2.0 notification envelope (no id).
type JSONRPCRequest ¶
type JSONRPCRequest struct {
JSONRPC string `json:"jsonrpc"`
ID string `json:"id"`
Method string `json:"method"`
Params json.RawMessage `json:"params"`
}
JSONRPCRequest JSON-RPC 2.0 request envelope.
type JSONRPCSuccessResponse ¶
type JSONRPCSuccessResponse struct {
JSONRPC string `json:"jsonrpc"`
ID string `json:"id"`
Result json.RawMessage `json:"result"`
}
JSONRPCSuccessResponse JSON-RPC 2.0 success response envelope.
type LaunchFunc ¶ added in v1.1.0
type LaunchFunc func(ctx context.Context, req LaunchRequest) (LaunchSpec, error)
LaunchFunc is called once per new command process or package install (not for replays or file transfers), after the session's files are synced and before it is spawned. A package install calls the package manager and may run install scripts, so a hook that confines or refuses commands should check LaunchRequest.PackageInstall too. It may choose the directory (for example from the session's metadata), wrap argv in a sandbox command (sandbox-exec, bwrap) and change the environment. Returning an error refuses the start: an *RPCError (NewReasonError) is answered as is, so the harness sees its data.reason; any other error is answered as spawn_failed.
As CoreOptions.Launch it is called once per bash tool call, before its command starts (Core's tool.call and LocalToolRoute, so ACPAgent's own tools). Argv is then the shell command (bash -lc <command>; cmd.exe /d /s /c <command> on Windows). A refusal ends the call with an error result "<reason>: <message>" (the route's Code is the reason) and nothing starts. Use the same function for both options to give the brain's own commands and process.* one admission check and one sandbox.
type LaunchRequest ¶ added in v1.1.0
type LaunchRequest struct {
// ProcessContext is the process.start's. For a bash tool (Tool set),
// SessionID is the tool call's session and ProcessID is empty (a tool call
// is no process.* process); a tool.call fills AgentSessionID, Metadata and
// Client from the session.assign, a LocalToolRoute (ACPAgent) sets
// AgentSessionID to its session and has no Metadata or Client.
ProcessContext
// Tool is "bash" when a bash tool call is about to start its command
// (CoreOptions.Launch), "" for process.start. ToolCallID is then the
// call's id.
Tool string
ToolCallID string
// PackageInstall is set for a process.start package_install and nil for
// a command. Argv, Cwd and Env are then the installer's fixed command
// (PackageInstallCommand): the hook may wrap it, change its environment
// or directory, or refuse it, but the packages come from here.
PackageInstall *ProcessPackageInstall
Argv []string
// Cwd is the requested cwd as sent (not resolved or confined); for a
// package install, the installer command's Dir.
Cwd string
// DefaultCwd is the session workspace, the cwd used when the hook
// returns no Dir and the request names none.
DefaultCwd string
// Env is the complete environment the process would get.
Env []string
}
LaunchRequest is one command process, package install or bash tool command about to start.
type LaunchSpec ¶ added in v1.1.0
type LaunchSpec struct {
// Dir is an absolute directory; it is not confined to the workspace.
Dir string
Argv []string
// Env is the complete environment.
Env []string
}
LaunchSpec is how the process starts. An empty field keeps the request's value: no Dir resolves the requested cwd inside the session workspace as without a hook, no Argv runs the requested command, a nil Env keeps the computed environment.
type Limits ¶
type Limits struct {
MaxInflightRequests int `json:"max_inflight_requests"`
MaxConcurrentProcessReads int `json:"max_concurrent_process_reads"`
MaxProcessReadBytes int `json:"max_process_read_bytes"`
MaxProcessWriteBytes int `json:"max_process_write_bytes"`
MaxProcessesPerSession int `json:"max_processes_per_session"`
MaxArtifactBytes int64 `json:"max_artifact_bytes"`
}
Limits Limits the executor must enforce, advertised in the v1.1 executor.register result (v1.1 §1.3).
type ListFilesInput ¶ added in v1.0.0
type ListFilesInput struct {
// Directory, relative to the session workspace.
Path string `json:"path,omitempty"`
}
ListFilesInput list_files input.
type LocalToolRoute ¶ added in v1.4.0
type LocalToolRoute struct {
// contains filtered or unexported fields
}
LocalToolRoute runs a brain's tool calls on this machine, in a Core: the hands are here. It is the counterpart of PlatformToolRoute, and the two are held to the same conformance suite (package conformance, cases T1–T11): a brain cannot tell which one it is talking to. What the platform's tool gateway does for a remote machine (ADR-0005), this route does for itself, because the brain is not trusted to have asked:
- the call must belong to the turn the route was made for: a call after the turn ended or was canceled, or from an older brain process once a newer turn of the session began, is refused (stale_turn);
- the tool's permission is re-evaluated from the permission mode and ToolPolicy: deny refuses (permission_denied), and ask needs the user's allow for this very call: the answer the platform gave under the deterministic approval id (ApprovalID), for the same tool and the same input, recorded with RecordApproval. Without one the call is refused (approval_required); with another tool, input or approval it is refused (approval_invalid). One approval is good for one call id;
- a call id runs at most once, also across restarts of the executor: the route keeps a small ledger per session under StateDir ("started" before the tool runs, "done" with its result after). A repeated call is answered with the first result (RouteResult.Replayed); one that was started and whose result was lost with the process has an unknown outcome and is not run again (outcome_unknown, ADR-0013). A refused call is not recorded: it did not run and may be asked for again once approved.
Its tools are the CMA agent_toolset (bash, read, write, edit, glob, grep) in the session's Workspace, through the Core's file roots. bash waits at most its timeout (and 55 s) and leaves a command that outlives the wait running: the call then answers with its pid and the file its output goes to (RouteResult.Background), like the platform gateway. When the Core has a CoreOptions.Launch hook, every bash command starts through it, as a process.start does; a command it refuses did not run: the call is not_forwarded with the hook's reason as Code (spawn_failed for a plain error). That answer is recorded like a result (the same call id is answered with it again), as the platform gateway records what the hands answered.
A LocalToolRoute is bound to one turn of one session and is safe for concurrent use. ACPAgent uses it for the turns whose hands are this machine.
func NewLocalToolRoute ¶ added in v1.4.0
func NewLocalToolRoute(opts LocalToolRouteOptions) (*LocalToolRoute, error)
NewLocalToolRoute returns the route of one turn to this machine's Core. It opens the session in the Core (idempotent) and begins the turn in the session's ledger: the same TurnID again (a restart) keeps what the ledger knows, another TurnID replaces it.
func (*LocalToolRoute) Call ¶ added in v1.4.0
func (r *LocalToolRoute) Call(ctx context.Context, c RouteCall) *RouteResult
Call implements ToolRoute.
func (*LocalToolRoute) CloseSession ¶ added in v1.4.0
func (r *LocalToolRoute) CloseSession()
CloseSession ends the session on this machine: its running tools and background commands stop, and its workspace state and turn state are released. It ends the session for every route of it.
func (*LocalToolRoute) Complete ¶ added in v1.4.0
func (r *LocalToolRoute) Complete()
Complete says the turn ended without being canceled or running out of time. A bash command left in the background then lives on after the turn's Context ends (until it exits, until an hour has passed or CloseSession); otherwise it is killed with the turn. Call it before canceling the Context.
func (*LocalToolRoute) RecordApproval ¶ added in v1.4.0
func (r *LocalToolRoute) RecordApproval(callID string, request InteractionRequestParams, answer InteractionResponseParams) error
RecordApproval records the platform's answer to the permission interaction of a call, which is what the route's gate checks before it runs an ask tool. request is what the brain asked the platform (AgentTurn.RequestInteraction) and answer what came back: only an allow or a deny is recorded (anything else, such as expired, leaves the call without an approval). The answer must be for the interaction asked; its id should be ApprovalID(session, turn, call), or the call is refused as approval_invalid.
type LocalToolRouteOptions ¶ added in v1.4.0
type LocalToolRouteOptions struct {
// Core runs the tools. Required. The route opens the session in it
// (Workspace) and CloseSession closes it.
Core *Core
// StateDir holds the turn state: one small file per session, written
// atomically. Required. Make it survive the executor's restarts to get the
// at-most-once guarantee across them.
StateDir string
// SessionID and TurnID are the platform session and turn the route is for.
// Required. A route made for a turn after another one of the same session
// started makes the earlier route stale.
SessionID string
TurnID string
// Workspace is the tools' working directory: relative paths and bash start
// there. It must be an existing absolute directory. Required.
Workspace string
// PermissionMode is the session's permission mode: "default" (also "") or
// "accept_edits" (write and edit are allowed without approval).
PermissionMode string
// ToolPolicy overrides the permission of tools (tool name to allow, ask or
// deny). A tool no mode default or override names is ask (fail-closed).
ToolPolicy map[string]string
// SessionFilesRoot is the executor's capabilities.session_files.root. When
// set, the file tools also reach this session's <root>/<SessionID>/uploads,
// skills (read-only) and outputs (writable), and nothing else below the
// root; see ACPAgentOptions.SessionFilesRoot. Absolute, or empty.
SessionFilesRoot string
// Context ends with the turn: a canceled Context ends the calls in flight,
// makes later calls stale_turn and ends commands left in the background
// (unless Complete was called first). Default: never ends.
Context context.Context
// OnLog tells about turn state problems.
OnLog func(level LogLevel, message string, err error)
}
LocalToolRouteOptions configures NewLocalToolRoute.
type MCPCapability ¶
type MCPCapability struct {
Stdio bool `json:"stdio,omitempty"`
HTTP bool `json:"http,omitempty"`
MaxServers int `json:"max_servers,omitempty"`
// The executor accepts transport.secret_env on stdio servers: resolved secret values it injects only into the server process environment, never persisting, logging or echoing them. Without it the server keeps secret: references in env, which the executor rejects.
SecretEnv bool `json:"secret_env,omitempty"`
}
MCPCapability Environment-origin MCP servers.
type MCPChannel ¶
type MCPChannel struct {
// contains filtered or unexported fields
}
MCPChannel is a raw MCP JSON-RPC transport on the executor MCP channel. The payload is unframed MCP JSON-RPC: the caller sends initialize, notifications/initialized, tools/list and tools/call directly, exactly as the protocol appendix defines. It runs on the client's transport: WebSocket, a Unix socket or in-process.
type MCPContentBlock ¶
type MCPContentBlock struct {
Type string `json:"type"`
Text string `json:"text,omitempty"`
Data string `json:"data,omitempty"`
MimeType string `json:"mimeType,omitempty"`
Resource any `json:"resource,omitempty"`
}
MCPContentBlock MCP tool content block. Large binary content must go to artifact storage.
type MCPImplementation ¶
MCPImplementation
type MCPInitializeParams ¶
type MCPInitializeParams struct {
ProtocolVersion string `json:"protocolVersion"`
Capabilities map[string]any `json:"capabilities"`
ClientInfo MCPImplementation `json:"clientInfo"`
}
MCPInitializeParams
type MCPInitializeResult ¶
type MCPInitializeResult struct {
ProtocolVersion string `json:"protocolVersion"`
Capabilities map[string]any `json:"capabilities"`
ServerInfo MCPImplementation `json:"serverInfo"`
}
MCPInitializeResult
type MCPJSONRPCError ¶
type MCPJSONRPCError struct {
Code int64 `json:"code"`
Message string `json:"message"`
Data any `json:"data,omitempty"`
}
MCPJSONRPCError
type MCPJSONRPCErrorResponse ¶
type MCPJSONRPCErrorResponse struct {
JSONRPC string `json:"jsonrpc"`
ID json.RawMessage `json:"id"`
Error MCPJSONRPCError `json:"error"`
}
MCPJSONRPCErrorResponse
type MCPJSONRPCNotification ¶
type MCPJSONRPCNotification struct {
JSONRPC string `json:"jsonrpc"`
Method string `json:"method"`
Params map[string]any `json:"params,omitempty"`
}
MCPJSONRPCNotification
type MCPJSONRPCRequest ¶
type MCPJSONRPCRequest struct {
JSONRPC string `json:"jsonrpc"`
ID json.RawMessage `json:"id"`
Method string `json:"method"`
Params map[string]any `json:"params,omitempty"`
}
MCPJSONRPCRequest
type MCPJSONRPCSuccessResponse ¶
type MCPJSONRPCSuccessResponse struct {
JSONRPC string `json:"jsonrpc"`
ID json.RawMessage `json:"id"`
Result any `json:"result"`
}
MCPJSONRPCSuccessResponse
type MCPProgressParams ¶
type MCPProgressParams struct {
ProgressToken json.RawMessage `json:"progressToken"`
Progress float64 `json:"progress"`
Total float64 `json:"total,omitempty"`
}
MCPProgressParams
type MCPServerConfig ¶
type MCPServerConfig struct {
ServerKey string `json:"server_key"`
ConnectionOrigin string `json:"connection_origin"`
Transport MCPServerTransport `json:"transport"`
}
MCPServerConfig
type MCPServerTransport ¶
type MCPServerTransport struct {
Type string `json:"type"`
// stdio: absolute or allowlisted executable. No shell, no sh -c.
Command string `json:"command,omitempty"`
Args []string `json:"args,omitempty"`
// stdio: working directory under the session workspace.
Cwd string `json:"cwd,omitempty"`
Env map[string]string `json:"env,omitempty"`
// stdio: sensitive variables the server resolved from env secret: references for this session, sent only to an executor that advertises capabilities.mcp.secret_env. The executor adds them to the server process environment only; it must not write them to disk, logs, argv or events, and drops them when the session ends. A name must not also appear in env.
SecretEnv map[string]string `json:"secret_env,omitempty"`
TimeoutMS int64 `json:"timeout_ms,omitempty"`
// Pins the executable when supplied.
CommandSHA256 string `json:"command_sha256,omitempty"`
// http: Streamable HTTP MCP endpoint.
URL string `json:"url,omitempty"`
}
MCPServerTransport Transport for one MCP server. stdio requires command; http requires url. Fields for the other transport are omitted.
type MCPTool ¶
type MCPTool struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
InputSchema map[string]any `json:"inputSchema"`
}
MCPTool
type MCPToolsCallParams ¶
type MCPToolsCallParams struct {
Name string `json:"name"`
Arguments map[string]any `json:"arguments"`
}
MCPToolsCallParams
type MCPToolsCallResult ¶
type MCPToolsCallResult struct {
Content []MCPContentBlock `json:"content"`
IsError bool `json:"isError,omitempty"`
StructuredContent any `json:"structuredContent,omitempty"`
}
MCPToolsCallResult
type MCPToolsListParams ¶
type MCPToolsListParams struct {
Cursor string `json:"cursor,omitempty"`
}
MCPToolsListParams
type MCPToolsListResult ¶
type MCPToolsListResult struct {
Tools []MCPTool `json:"tools"`
NextCursor *string `json:"nextCursor,omitempty"`
}
MCPToolsListResult
type MethodDirection ¶
type MethodDirection string
MethodDirection is the direction a JSON-RPC method travels.
const ( DirectionExecutorToHarness MethodDirection = "executor-to-harness" DirectionHarnessToExecutor MethodDirection = "harness-to-executor" DirectionBidirectional MethodDirection = "bidirectional" )
type MethodSpec ¶
type MethodSpec struct {
Name string
Direction MethodDirection
Notification bool
Since string
Capability string
IdempotentBy string
}
MethodSpec describes one executor protocol method. Since is the first protocol that has it; Capability is the capability bit the harness checks before sending it (empty: always available).
type ModelTokenRefreshParams ¶ added in v1.3.0
type ModelTokenRefreshParams struct {
// Platform session id of the turn.
SessionID string `json:"session_id"`
// Platform id of the running turn the token is for.
TurnID string `json:"turn_id"`
}
ModelTokenRefreshParams is the params object of model_token.refresh.
type ModelTokenRefreshResult ¶ added in v1.3.0
type ModelTokenRefreshResult struct {
// Bearer token for model_base_url. Valid until expires_at.
ModelToken string `json:"model_token"`
// Base URL the token is for (an OpenAI / Anthropic base URL path).
ModelBaseURL string `json:"model_base_url"`
// RFC 3339 time the token stops being accepted.
ExpiresAt string `json:"expires_at"`
}
ModelTokenRefreshResult model_token.refresh result: the credential for the turn's next model calls, in the form of the turn.start metadata model_base_url and model_token.
func SendModelTokenRefresh ¶ added in v1.3.0
func SendModelTokenRefresh(ctx context.Context, rpc RPC, params ModelTokenRefreshParams) (ModelTokenRefreshResult, error)
SendModelTokenRefresh calls model_token.refresh.
type NotificationMethod ¶ added in v1.0.0
NotificationMethod is an executor-to-harness notification with params P.
type Options ¶
type Options struct {
// EnvironmentKey is the bearer of the token exchange: an environment key
// (POST /v1/environments/{EnvironmentID}/token), or a machine daemon token
// for a machine-scoped executor (POST /v1/machines/{MachineID}/token).
EnvironmentKey string
// EnvironmentID is the selfhost environment. EnvironmentID and MachineID
// are alternatives: setting both is an error. With neither the client
// registers a machine-scoped executor on the legacy alias
// POST /api/v1/executors/token (removed in contract 2.0).
EnvironmentID string
// MachineID is the machine of a machine-scoped executor, taken from
// BMA_MACHINE_ID (MachineIDEnv) when empty and EnvironmentID is empty.
// The id must equal the machine of the credential, otherwise the server
// answers 404.
MachineID string
Executor ExecutorInfo
Capabilities Capabilities
// Labels are reported with executor.register (ExecutorInfo.Labels, contract
// 1.4.0) and added to Executor.Labels: at most 32, each 1-64 characters of
// a-z 0-9 . _ - . They are the machine owner's local configuration; the
// platform accepts them as given and uses them only to narrow a choice
// among machines the project is already authorized to use, never for an
// authorization or security decision.
Labels []string
// RemoteBrain is the machine owner's consent to let a brain that runs on
// another machine use this machine as its hands (Capabilities.RemoteBrain,
// contract 1.4.0). It is off unless the owner turns it on here, in the
// executor's local configuration; the platform only reads it back and has
// no way to switch it on. It applies to a machine the tenant owns; a
// platform-hosted brain driving this machine does not need it.
RemoteBrain bool
// Protocol is the WebSocket subprotocol and executor.register protocol.
// Defaults to ProtocolV11.
Protocol string
BaseURL string
WSURL string
// TokenSource replaces the token exchange bootstrap, for example
// StaticToken for a local harness. When set, EnvironmentKey and BaseURL
// are not used.
TokenSource func(ctx context.Context) (ExecutorTokenResponse, error)
// Dial opens the control connection. Defaults to WebSocketDialer with
// HTTPClient; see UnixSocketDialer, ListenUnixSocket and InProcessDialer.
Dial Dialer
// HTTPClient is used for the token request, artifact uploads and the
// default WebSocket dial. Defaults to http.DefaultClient.
HTTPClient *http.Client
// RequestTimeout bounds one JSON-RPC request. Defaults to 30s.
RequestTimeout time.Duration
// HeartbeatInterval overrides the interval returned by executor.register.
HeartbeatInterval time.Duration
// HeartbeatLoad is sampled for each heartbeat.
HeartbeatLoad func() *ExecutorLoad
// MaxReconnectAttempts bounds consecutive failed reconnects; the client
// then ends with ErrReconnectExhausted (see Done and Err). Zero (the
// default) or a negative value reconnects until Stop.
MaxReconnectAttempts int
// ReconnectBaseDelay is the first reconnect backoff (default 1s); it
// doubles per failed attempt up to ReconnectMaxDelay, with jitter.
ReconnectBaseDelay time.Duration
// ReconnectMaxDelay caps the reconnect backoff before jitter. Defaults
// to 60s.
ReconnectMaxDelay time.Duration
Random func() float64
// ToolResultRetryAttempts is the total number of attempts for tool.result,
// session.ready and session.ended, including the first. It defaults to 5;
// set it to 1 to disable retries.
ToolResultRetryAttempts int
// ToolResultRetryBaseDelay is the first backoff for retryable failures.
// It defaults to 250ms and doubles per attempt up to 10s.
ToolResultRetryBaseDelay time.Duration
// OnToolResultLost is called by the dispatch path when a tool result could
// not be accepted after all retries, or the error is not retryable. The
// adapter must persist the result and replay it with the same
// tool_call_id; the client never drops a result silently.
OnToolResultLost func(params ToolResultParams, err error)
OnLog func(LogEvent)
}
Options configures a Client.
type PackageInstallCommand ¶
PackageInstallCommand is the fixed command one package install runs. Env is its complete environment. Privileged runs it with the executor's own identity instead of CoreOptions.RunAs: system package managers need root, user-level ones must not get it.
type PackageInstaller ¶
type PackageInstaller interface {
PackageInstallCommand(processID string, install ProcessPackageInstall) (PackageInstallCommand, error)
}
PackageInstaller builds the command for a process.start package_install. The core has already checked manager and packages against the contract (one of apt, pip, npm; plain package names only), so the installer passes the packages as separate arguments after its own fixed options.
type PlatformToolRoute ¶ added in v1.4.0
type PlatformToolRoute struct {
// contains filtered or unexported fields
}
PlatformToolRoute sends a brain's tool calls to the platform's execute-only tool gateway (ADR-0005), an MCP Streamable HTTP endpoint, instead of running them here: the hands are on another machine. The gateway does what the local route does for itself (token and epoch, policy re-check, approval check, at-most-once by idempotency key) and runs the tool in the session's machine; this side only speaks its wire and maps the answer to the same RouteResult as the local route.
The tool credential (session x turn x epoch) lives in memory only: it is never written to the state directory, to a log, to an error text or by String/%v. It is replaced before it expires (toolsCredential).
A brain gets one from AgentTurn.Tools for a turn whose turn.start metadata carries tools_mcp_* (the hands are on another machine), with the token refreshed through tools_token.refresh; NewPlatformToolRoute builds one from a credential the caller manages itself. ACPAgent uses it the same way; any other turn gets its local route.
func NewPlatformToolRoute ¶ added in v1.4.0
func NewPlatformToolRoute(opts PlatformToolRouteOptions) (*PlatformToolRoute, error)
NewPlatformToolRoute returns the route of one turn to the platform's tool gateway. Endpoint, Token, SessionID and TurnID are required. Most brains use AgentTurn.Tools instead, which fills this from turn.start and keeps the token fresh; use this when the credential comes from somewhere else.
func (*PlatformToolRoute) Call ¶ added in v1.4.0
func (r *PlatformToolRoute) Call(ctx context.Context, c RouteCall) *RouteResult
Call implements ToolRoute.
func (*PlatformToolRoute) GoString ¶ added in v1.4.0
func (r *PlatformToolRoute) GoString() string
GoString keeps the credential out of %#v.
func (*PlatformToolRoute) String ¶ added in v1.4.0
func (r *PlatformToolRoute) String() string
String keeps the credential out of %v / %+v / %s.
type PlatformToolRouteOptions ¶ added in v1.4.0
type PlatformToolRouteOptions struct {
// Endpoint is the gateway's MCP URL.
Endpoint string
// Token is the turn's tool credential.
Token string
// ExpiresAt is when Token stops being accepted (zero: not said, never refreshed).
ExpiresAt time.Time
// Refresh replaces the credential before it expires (tools_token.refresh); nil: never refreshed.
Refresh func(ctx context.Context) (ToolsTokenRefreshResult, error)
// OnLog tells about a failed refresh (it is also retried; see toolsCredential).
OnLog func(level LogLevel, message string, err error)
TurnID string
// SessionID is the platform session of the turn (required by NewPlatformToolRoute).
SessionID string
// ApprovalFor returns the interaction id of the user's approval of a call,
// or "" when there is none (ADR-0005: presented in _meta, checked by the gateway).
ApprovalFor func(callID string) string
// SyncWait, when set, is sent as the call's synchronous wait ceiling.
SyncWait time.Duration
// HTTPClient defaults to a client without a timeout; ctx ends a call.
HTTPClient *http.Client
}
type Principal ¶
type Principal struct {
ExecutorID string
}
Principal is what HarnessOptions.Authenticate learns from an upgrade request. A non-empty ExecutorID pins the executor identity: register and MCP channels must belong to it.
type ProcessCapability ¶
type ProcessCapability struct {
Enabled bool `json:"enabled"`
MaxProcesses int `json:"max_processes,omitempty"`
BufferBytes int `json:"buffer_bytes,omitempty"`
// Accepts process.start io_mode "pty".
PTY bool `json:"pty,omitempty"`
// Accepts process.start file_transfer.
FileTransfer bool `json:"file_transfer,omitempty"`
// Accepts process.start git_credentials.
GitCredentials bool `json:"git_credentials,omitempty"`
// Accepts process.start package_install.
PackageInstall bool `json:"package_install,omitempty"`
}
ProcessCapability v1.1 process.* support. pty, file_transfer, package_install and git_credentials are additive: the harness only sends the matching process.start fields to an executor that set them, and fails the process explicitly otherwise.
type ProcessContext ¶ added in v1.1.0
type ProcessContext struct {
// SessionID is the executor session (session.assign) of the process.
SessionID string
ProcessID string
// AgentSessionID is process.start metadata agent_session_id: the agent
// session the process runs for ("" when the harness named none). Pass it
// to Client.SessionContextByID, or the process id to
// Client.SessionContext, to read the session's metadata.
AgentSessionID string
Metadata map[string]string
// Client is the connection of the brain that started the process (for
// machine-token requests such as a file transfer).
Client *Client
}
ProcessContext identifies the process a hook runs for.
type ProcessFileTransfer ¶
type ProcessFileTransfer struct {
Direction string `json:"direction"`
LocalPath string `json:"local_path"`
}
ProcessFileTransfer Replaces argv: the executor moves one file between the machine and the process BMA file endpoint and reports the outcome in ProcessState.file_transfer. Requires process.file_transfer.
type ProcessListParams ¶
type ProcessListParams struct {
SessionID string `json:"session_id"`
}
ProcessListParams is the params object of process.list.
type ProcessListResult ¶
type ProcessListResult struct {
Processes []ProcessState `json:"processes"`
}
ProcessListResult process.list result.
type ProcessOptions ¶
type ProcessOptions struct {
// Env is set on every process (not on bash tools) over the request env,
// for example a canonical skill root such as BMA_HOME.
Env map[string]string
FileTransfer FileTransferer
GitCredentials GitCredentialGranter
// PackageInstaller serves process.start package_install.
PackageInstaller PackageInstaller
// Launch runs before each new command process starts; see LaunchFunc.
Launch LaunchFunc
// SessionFiles syncs each agent session's files below its root, which
// is advertised as capabilities.session_files.root; see SessionFiles.
SessionFiles *SessionFiles
}
ProcessOptions configures the process capability. Nil hooks leave the matching capability bit unset, and the core rejects those process.start fields with capability_unavailable.
type ProcessPackageInstall ¶
type ProcessPackageInstall struct {
Manager string `json:"manager"`
Packages []string `json:"packages"`
}
ProcessPackageInstall Replaces argv: the executor installs packages with a fixed command it builds itself, streaming the package manager output as the process output. apt installs from the machine's configured (official) sources with the executor's own privileges; pip (--user) and npm (global under the workload user's ~/.local) run as the workload user. Package names are plain names only: no options, versions, paths or URLs. Requires process.package_install.
type ProcessReadParams ¶
type ProcessReadParams struct {
SessionID string `json:"session_id"`
ProcessID string `json:"process_id"`
Stream string `json:"stream"`
Cursor int64 `json:"cursor"`
MaxBytes int `json:"max_bytes,omitempty"`
WaitMS int64 `json:"wait_ms,omitempty"`
}
ProcessReadParams is the params object of process.read.
type ProcessReadResult ¶
type ProcessReadResult struct {
ProcessID string `json:"process_id"`
Stream string `json:"stream"`
// Base64 bytes from from_cursor to next_cursor.
Data string `json:"data"`
FromCursor int64 `json:"from_cursor"`
NextCursor int64 `json:"next_cursor"`
EarliestCursor int64 `json:"earliest_cursor"`
Gap bool `json:"gap"`
Truncated bool `json:"truncated"`
EOF bool `json:"eof"`
State string `json:"state"`
EndedAt string `json:"ended_at,omitempty"`
Reason string `json:"reason,omitempty"`
ExitCode *int `json:"exit_code"`
ExitSignal *string `json:"exit_signal"`
FileTransfer *FileTransferResult `json:"file_transfer,omitempty"`
}
ProcessReadResult process.read result.
type ProcessSignalParams ¶
type ProcessSignalParams struct {
SessionID string `json:"session_id"`
ProcessID string `json:"process_id"`
// Only meaningful for process.terminate.
GraceMS *int64 `json:"grace_ms,omitempty"`
}
ProcessSignalParams is the params object of process.interrupt and process.terminate.
type ProcessStartParams ¶
type ProcessStartParams struct {
SessionID string `json:"session_id"`
ProcessID string `json:"process_id"`
// Command and arguments (at most 256 entries, 4 KiB each, 16 KiB total). Must be empty when file_transfer or package_install is set.
Argv []string `json:"argv"`
Cwd string `json:"cwd,omitempty"`
Env map[string]string `json:"env,omitempty"`
Stdin string `json:"stdin,omitempty"`
// Empty keeps separate stdout/stderr streams.
Stderr string `json:"stderr,omitempty"`
WaitMS int64 `json:"wait_ms,omitempty"`
// Kills the process and ends it as failed with reason "timeout".
TimeoutMS int64 `json:"timeout_ms,omitempty"`
// Who started the process. A process an agent tool started (a command, a file transfer, a package install) always carries agent_session_id (the public agent session id) and tool_call_id; it carries no initiator. A process the platform started on its own, such as the machine desktop agent, carries initiator "platform" and no agent_session_id. A process with neither is not started by the harness: an executor that resolves a directory, files or owner per session refuses it (reason session_rejected) instead of using a default. Human console terminals are terminal.attach, not process.start.
Metadata map[string]string `json:"metadata,omitempty"`
// Requires capability process.pty.
IOMode string `json:"io_mode,omitempty"`
// Requires capability process.file_transfer. Excludes argv entries, io_mode and git_credentials.
FileTransfer *ProcessFileTransfer `json:"file_transfer,omitempty"`
// Requires capability process.package_install. Excludes argv entries, io_mode, file_transfer and git_credentials.
PackageInstall *ProcessPackageInstall `json:"package_install,omitempty"`
// Installs a per-process Git credential helper for https://github.com that fetches short-lived tokens for this process while it runs. Requires capability process.git_credentials.
GitCredentials bool `json:"git_credentials,omitempty"`
}
ProcessStartParams is the params object of process.start.
type ProcessState ¶
type ProcessState struct {
ProcessID string `json:"process_id"`
State string `json:"state"`
PID int `json:"pid,omitempty"`
StartedAt string `json:"started_at,omitempty"`
EndedAt string `json:"ended_at,omitempty"`
Reason string `json:"reason,omitempty"`
Cursors Cursors `json:"cursors"`
ExitCode *int `json:"exit_code"`
ExitSignal *string `json:"exit_signal"`
Stderr string `json:"stderr,omitempty"`
Accepted bool `json:"accepted,omitempty"`
FileTransfer *FileTransferResult `json:"file_transfer,omitempty"`
}
ProcessState Result of process.start/interrupt/terminate and one process.list entry. ended_at (RFC 3339, executor clock) is set once the process is no longer running; reason explains a "failed" state (for example "timeout"). A spawn failure never creates a state: it is the process.start error with data.reason "spawn_failed".
type ProcessStatusParams ¶
type ProcessStatusParams struct {
SessionID string `json:"session_id"`
ProcessID string `json:"process_id"`
State string `json:"state"`
ExitCode *int `json:"exit_code,omitempty"`
ExitSignal *string `json:"exit_signal,omitempty"`
EndedAt string `json:"ended_at,omitempty"`
Reason string `json:"reason,omitempty"`
ObservedAt string `json:"observed_at"`
}
ProcessStatusParams is the params object of process.status.
type ProcessWriteParams ¶
type ProcessWriteParams struct {
SessionID string `json:"session_id"`
ProcessID string `json:"process_id"`
Data string `json:"data,omitempty"`
CloseStdin bool `json:"close_stdin,omitempty"`
}
ProcessWriteParams is the params object of process.write.
type ProcessWriteResult ¶
type ProcessWriteResult struct {
Accepted bool `json:"accepted"`
}
ProcessWriteResult process.write result.
type RPC ¶
type RPC interface {
Call(ctx context.Context, method string, params any, result any) error
Notify(ctx context.Context, method string, params any) error
}
RPC is the transport contract implemented by the handwritten client.
type RPCError ¶
type RPCError struct {
Code int
Message string
Data *JSONRPCErrorData
}
RPCError is a JSON-RPC error returned by the peer, or returned by a handler to answer with a specific code and data.
func NewReasonError ¶ added in v1.1.0
NewReasonError returns the JSON-RPC error a handler or a Launch hook returns to refuse a request with a machine-readable reason, for example NewReasonError(CodeForbidden, ReasonSessionRejected, "not this machine's user").
type ReadInput ¶ added in v1.0.0
type ReadInput struct {
// File path, relative to the session workspace.
Path string `json:"path"`
// First line to return, 1-based.
Offset int64 `json:"offset,omitempty"`
// Maximum number of lines.
Limit int64 `json:"limit,omitempty"`
}
ReadInput read input: return lines of a text file.
type RemoteBrainCapability ¶ added in v1.3.0
type RemoteBrainCapability struct {
Enabled bool `json:"enabled"`
}
RemoteBrainCapability Contract 1.4.0. The machine's owner allows a brain that runs on another machine to use this machine as its hands (platform tools routed here for a session whose brain machine is a different one). Set only by the executor's local configuration (bmad configuration or SDK Options.RemoteBrain); the platform reads it back and cannot switch it on through any API. Absent or enabled=false: off, which is also what an executor that predates 1.4.0 means. It applies to a BYO (tenant-owned) machine; a platform pool machine does not need it. It does not restrict a platform-hosted brain driving this machine (project authorization is enough there), and a brain and hands on one machine never need it.
type Request ¶
type Request struct {
Brain string
Method string
// ID is the JSON-RPC request id, the idempotency key of retried writes.
ID string
Params json.RawMessage
// Session is the active session named by params.session_id for a
// SessionScoped capability, nil otherwise.
Session *CoreSession
Client *Client
}
Request is one inbound request routed to a Capability handler.
type RequestMethod ¶ added in v1.0.0
RequestMethod is a harness-to-executor request with params P and result R.
func (RequestMethod[P, R]) Handle ¶ added in v1.0.0
func (m RequestMethod[P, R]) Handle(client *Client, handler func(ctx context.Context, params P) (R, error))
Handle serves the request on client, replacing an earlier handler. Params that do not decode are answered -32602; return an *RPCError for another JSON-RPC error. RequestID(ctx) is the request's JSON-RPC id.
type RouteBackground ¶ added in v1.4.0
RouteBackground is a command still running after its call returned.
type RouteCall ¶ added in v1.4.0
type RouteCall struct {
// ID is the brain's tool call id. It is the call's idempotency identity:
// the same ID in the same turn is run once, also when the brain process
// restarts and asks again. It must be unique within the turn.
ID string
// ToolUseID is the event id of the call's agent.tool_use event (optional;
// it ties the gateway's audit record to the event).
ToolUseID string
// Name is the tool: bash, read, write, edit, glob or grep.
Name string
// Input is the tool's input as the brain's JSON decoder produced it.
Input map[string]any
// ApprovalID is the interaction id of the user's approval of this call
// (AgentTurn.RequestInteraction answered allow), or "" when the call needs
// none. The gateway verifies it: one approval is good for one call, the
// same tool and the same input.
ApprovalID string
}
RouteCall is one tool call of a brain, in the CMA agent_toolset input shape (bash, read, write, edit, glob, grep; for example {"command": "ls"} for bash).
type RouteResult ¶ added in v1.4.0
type RouteResult struct {
// Outcome is a RouteOutcome* value.
Outcome string
// Code is the reason of a refusal or an unclear outcome, for example
// permission_denied, approval_required, approval_invalid, stale_turn,
// environment_unavailable, in_progress, idempotency_key_reused,
// tools_unavailable (open set; contract schemas/common.json lists them).
Code string
// Text is the tool's output, or "<Code>: <detail>" when Code is set.
Text string
// IsError: the call failed, was refused or its outcome is unknown.
IsError bool
// Replayed: the answer was saved from an earlier call with the same ID
// (not run again).
Replayed bool
// Background: a command left running when the call stopped waiting
// (bash past its synchronous wait).
Background *RouteBackground
// Images are image blocks of the result (computer_observe screenshots),
// for the model with Text. A replayed result has none.
Images []ContentBlock
}
RouteResult is the answer to a RouteCall.
type RunAs ¶
type RunAs struct {
UID, GID uint32
// Groups are the supplementary groups (for example one that may write a
// shared session directory); empty means none.
Groups []uint32
// Home and User replace the executor's HOME and USER.
Home, User string
}
RunAs is a workload OS identity (CoreOptions.RunAs).
type Session ¶
type Session struct {
// Tools has one typed entry per built-in tool: Tools.Bash.Call(...).
Tools HarnessTools
// contains filtered or unexported fields
}
Session is one session bound to an executor.
func (*Session) CallTool ¶
func (s *Session) CallTool(ctx context.Context, params ToolCallParams) (ToolResultParams, error)
CallTool sends tool.call and waits for its tool.result. It is idempotent by ToolCallID (generated when empty): repeating an id joins the in-flight call or returns the recorded result without re-dispatching. Canceling ctx stops waiting only; use CancelTool to abort the tool. The result is recorded even if nobody is waiting, so a later CallTool with the same id returns it.
func (*Session) CancelTool ¶
CancelTool sends tool.cancel. The waiting CallTool still receives the executor's tool.result (outcome canceled when the abort won the race).
func (*Session) MCP ¶
MCP waits for the MCP channel for serverKey (one of the session.assign mcp_servers) and returns it. A newer channel for the same key replaces the old one; the session's end closes all of them.
type SessionAssignHandler ¶
type SessionAssignHandler func(ctx context.Context, params SessionAssignParams) (SessionAssignResult, error)
SessionAssignHandler handles an inbound session.assign.
type SessionAssignParams ¶
type SessionAssignParams struct {
SessionID string `json:"session_id"`
WorkID string `json:"work_id"`
AgentID string `json:"agent_id,omitempty"`
EnvironmentID string `json:"environment_id"`
DeadlineMS int64 `json:"deadline_ms,omitempty"`
Lease Lease `json:"lease"`
Resources []json.RawMessage `json:"resources,omitempty"`
MCPServers []MCPServerConfig `json:"mcp_servers,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
}
SessionAssignParams is the params object of session.assign.
type SessionAssignResult ¶
type SessionAssignResult struct {
Accepted bool `json:"accepted"`
SessionID string `json:"session_id"`
}
SessionAssignResult session.assign result.
type SessionCloseParams ¶
type SessionCloseParams struct {
SessionID string `json:"session_id"`
Reason string `json:"reason"`
}
SessionCloseParams is the params object of session.close.
type SessionCloseResult ¶
type SessionCloseResult struct {
Closed bool `json:"closed"`
}
SessionCloseResult session.close result.
type SessionContext ¶ added in v1.1.0
type SessionContext struct {
ID string `json:"id"`
EnvironmentID string `json:"environment_id"`
Metadata map[string]string `json:"metadata"`
CreatedAt time.Time `json:"created_at"`
}
SessionContext is what BMA tells this machine about an agent session it serves (GET /api/v1/daemon/processes/{process_id}/session and GET /api/v1/daemon/sessions/{session_id}): the session's environment and the metadata its creator set, never agent configuration or credentials. Executors read it to resolve a reference the caller put in metadata (a project folder, an owner) before running anything, as Claude Managed Agents workers read the session's metadata for a claimed work item.
type SessionEndedParams ¶
type SessionEndedParams struct {
SessionID string `json:"session_id"`
Reason string `json:"reason"`
}
SessionEndedParams is the params object of session.ended.
type SessionErrorEvent ¶
type SessionErrorEvent struct {
Type string `json:"type"`
Error AgentErrorInfo `json:"error"`
}
SessionErrorEvent A turn-level error. A failed turn still ends with session.status_idle turn_outcome=failed.
type SessionEvent ¶
type SessionEvent struct {
Type string `json:"type"`
ToolUseID string `json:"tool_use_id,omitempty"`
Content []ContentBlock `json:"content,omitempty"`
IsError bool `json:"is_error,omitempty"`
}
SessionEvent Durable session event emitted by the executor.
type SessionEventDeltaParams ¶
type SessionEventDeltaParams struct {
SessionID string `json:"session_id"`
TurnID string `json:"turn_id"`
EventID string `json:"event_id"`
EventType string `json:"event_type"`
// Content block index within the event.
Index int64 `json:"index"`
// Text appended to the block.
Text string `json:"text"`
}
SessionEventDeltaParams is the params object of session.event_delta.
type SessionEventParams ¶
type SessionEventParams struct {
SessionID string `json:"session_id"`
// Agent sessions; the turn that produced the event.
TurnID string `json:"turn_id,omitempty"`
// Agent sessions; executor-assigned, unique within the session, stable across resends.
EventID string `json:"event_id,omitempty"`
// Agent sessions; starts at 1 and increases by 1 per durable event within the session.
Sequence int64 `json:"sequence,omitempty"`
// Agent sessions; optional key the executor keeps for this event across process restarts (its outbox entry id, for example). A new executor epoch renumbers sequence and suffixes event_id, so only this key lets the harness recognize an event it stored just before the executor crashed. The harness acknowledges an event whose key the session already stored as a duplicate (sequence advanced, nothing added to the session log), in any epoch. Without it an event resent in a new epoch is stored again (at-least-once).
IdempotencyKey string `json:"idempotency_key,omitempty"`
Event json.RawMessage `json:"event"`
}
SessionEventParams is the params object of session.event.
type SessionEventResult ¶
type SessionEventResult struct {
Accepted bool `json:"accepted"`
EventID string `json:"event_id"`
// Agent sessions: highest contiguous sequence the platform has persisted for the session. A duplicate event is accepted and reports the current value.
AckedSequence int64 `json:"acked_sequence,omitempty"`
}
SessionEventResult session.event result.
func SendSessionEvent ¶
func SendSessionEvent(ctx context.Context, rpc RPC, params SessionEventParams) (SessionEventResult, error)
SendSessionEvent calls session.event.
type SessionFileTransferer ¶ added in v1.1.0
type SessionFileTransferer interface {
FileTransferer
TransferSessionFile(ctx context.Context, process ProcessContext, transfer ProcessFileTransfer) (FileTransferResult, error)
}
SessionFileTransferer is a FileTransferer that also learns which session the transfer runs for (for example to check the path against the folder that session may use). When ProcessOptions.FileTransfer implements it, TransferSessionFile is called instead of TransferFile.
func NewFileTransferer ¶ added in v1.3.0
func NewFileTransferer() SessionFileTransferer
NewFileTransferer returns the FileTransferer for ProcessOptions.FileTransfer of a machine-scoped executor (ErrMachineTokenRequired otherwise, on the first transfer). An upload streams a regular file (at most MaxFileTransferBytes) and is checked against the digest BMA stored. A download streams into a temporary file next to the destination and replaces it only after the length and sha256 match, keeping the destination's permissions (on Windows: its read-only attribute); a leading "~" in the path is the user's home directory (USERPROFILE on Windows). The workload's own permissions are the executor's: a privileged executor should give a Launch hook, not this, the job of confining paths. edit_file downloads are not supported (BMA then answers the agent that the executor cannot edit).
type SessionFiles ¶ added in v1.1.0
type SessionFiles struct {
// contains filtered or unexported fields
}
SessionFiles syncs the session files of an executor that declares capabilities.session_files. Pass it as ProcessOptions.SessionFiles (the process capability then advertises the root and syncs before each process of an agent session) and run Run for the output uploads. It needs a machine-scoped executor (ErrMachineTokenRequired).
func NewSessionFiles ¶ added in v1.1.0
func NewSessionFiles(opts SessionFilesOptions) (*SessionFiles, error)
NewSessionFiles validates the root and creates it (0700) if needed.
func (*SessionFiles) Dirs ¶ added in v1.1.0
func (f *SessionFiles) Dirs(sessionID string) (uploads, outputs string)
Dirs returns the uploads and outputs directories of an agent session, for example for a Launch hook that confines a sandbox to them.
func (*SessionFiles) Root ¶ added in v1.1.0
func (f *SessionFiles) Root() string
Root is the advertised capabilities.session_files.root.
func (*SessionFiles) Run ¶ added in v1.1.0
func (f *SessionFiles) Run(ctx context.Context)
Run uploads changed outputs until ctx ends, then uploads what is left.
type SessionFilesCapability ¶ added in v1.1.0
type SessionFilesCapability struct {
// Absolute, already-expanded, clean path on the executor host (no ~, no . or .. segments, no trailing /).
Root string `json:"root"`
}
SessionFilesCapability Executor-owned per-session file layout. The harness derives <root>/<agent_session_id>/uploads (read-only session inputs) and <root>/<agent_session_id>/outputs (deliverables) from it, with agent_session_id as sent in process.start metadata, and uses these real paths in prompts, tool descriptions, write rules and the session files manifest. Absent: the harness keeps /mnt/session/uploads and /mnt/session/outputs. With the fs capability skills_per_session the same tree also holds <root>/<agent_session_id>/skills (the session's skills view, read-only). Fixed at executor.register: executor.capabilities.update does not change it. Machine-scoped executors only.
type SessionFilesOptions ¶ added in v1.1.0
type SessionFilesOptions struct {
// Root is the absolute, already-expanded directory that holds every
// session's files; it is advertised as capabilities.session_files.root
// and BMA shows the agent <Root>/<session id>/{uploads,outputs}. Keep it
// apart from the executor's own state and IPC directories.
Root string
// MaxOutputBytes is the largest output uploaded (default and maximum
// 1 GiB); larger files are skipped and logged.
MaxOutputBytes int64
OnLog func(LogEvent)
}
SessionFilesOptions configures NewSessionFiles.
type SessionMemoryResource ¶
type SessionMemoryResource struct {
Type string `json:"type"`
MemoryStoreID string `json:"memory_store_id"`
MountPath string `json:"mount_path"`
}
SessionMemoryResource A memory store mounted into the session workspace.
type SessionReadyParams ¶
type SessionReadyParams struct {
SessionID string `json:"session_id"`
WorkID string `json:"work_id"`
LeaseToken string `json:"lease_token"`
}
SessionReadyParams is the params object of session.ready.
type SessionStatusIdleEvent ¶
type SessionStatusIdleEvent struct {
Type string `json:"type"`
StopReason StopReason `json:"stop_reason"`
TurnOutcome string `json:"turn_outcome"`
}
SessionStatusIdleEvent The turn ended. It is the last event of its turn_id; the platform publishes the turn as finished only after it accepted this event and every lower sequence.
type SessionStatusParams ¶
type SessionStatusParams struct {
SessionID string `json:"session_id"`
Status string `json:"status"`
Detail string `json:"detail,omitempty"`
}
SessionStatusParams is the params object of session.status.
type SessionStatusRunningEvent ¶
type SessionStatusRunningEvent struct {
Type string `json:"type"`
}
SessionStatusRunningEvent The local agent started working on the turn.
type SessionStopHandler ¶
type SessionStopHandler func(ctx context.Context, params SessionStopParams) (SessionStopResult, error)
SessionStopHandler handles an inbound session.stop.
type SessionStopParams ¶
type SessionStopParams struct {
SessionID string `json:"session_id"`
Reason string `json:"reason"`
DeadlineMS int64 `json:"deadline_ms,omitempty"`
}
SessionStopParams is the params object of session.stop.
type SessionStopResult ¶
type SessionStopResult struct {
Stopped bool `json:"stopped"`
}
SessionStopResult session.stop result.
type ShellCapability ¶
type ShellCapability struct {
Enabled bool `json:"enabled"`
}
ShellCapability v1 one-shot shell tools.
type SkillInstallParams ¶
type SkillInstallParams struct {
MachineID string `json:"machine_id"`
SkillID string `json:"skill_id"`
RevisionID string `json:"revision_id"`
Digest string `json:"digest"`
DownloadToken string `json:"download_token"`
// Unix seconds.
DownloadExpiresAt int64 `json:"download_expires_at"`
}
SkillInstallParams is the params object of skill.install.
type SkillInstallResult ¶
type SkillInstallResult struct {
State string `json:"state"`
ErrorCode string `json:"error_code,omitempty"`
Error string `json:"error,omitempty"`
}
SkillInstallResult skill.install result. state is "ready", or "failed" with error_code and error.
type SkillInstaller ¶
type SkillInstaller func(ctx context.Context, params SkillInstallParams) SkillInstallResult
SkillInstaller installs one skill revision; the result state is "ready" or "failed" with error_code and error. It must be idempotent by (skill_id, revision_id, digest).
type SkillsCapability ¶
type SkillsCapability struct {
Install bool `json:"install"`
}
SkillsCapability skill.install support. Machine-scoped executors only.
type StopReason ¶
type StopReason struct {
Type string `json:"type"`
}
StopReason Why the turn stopped.
type TerminalAttachParams ¶
type TerminalAttachParams struct {
TerminalID string `json:"terminal_id"`
Epoch int64 `json:"epoch"`
StreamID string `json:"stream_id"`
CanWrite bool `json:"can_write"`
FromSeq int64 `json:"from_seq"`
AckSeq int64 `json:"ack_seq"`
Host TerminalHost `json:"host"`
}
TerminalAttachParams is the params object of terminal.attach.
type TerminalAttachResult ¶
type TerminalAttachResult struct {
Accepted bool `json:"accepted"`
WriterEpoch uint64 `json:"writer_epoch"`
}
TerminalAttachResult terminal.attach result, returned after the host socket is connected and the attached frame was written on it.
type TerminalCapability ¶
type TerminalCapability struct {
Enabled bool `json:"enabled"`
Kinds []string `json:"kinds,omitempty"`
MaxSessions int `json:"max_sessions,omitempty"`
}
TerminalCapability v1.1 terminal.* support. Machine-scoped executors only.
type TerminalCloseParams ¶
type TerminalCloseParams struct {
TerminalID string `json:"terminal_id"`
Reason string `json:"reason,omitempty"`
}
TerminalCloseParams is the params object of terminal.close.
type TerminalCloseResult ¶
type TerminalCloseResult struct {
Closed bool `json:"closed"`
ExitCode *int `json:"exit_code,omitempty"`
}
TerminalCloseResult terminal.close result. Idempotent: closing an unknown or closed terminal returns closed=true.
type TerminalErrorData ¶
type TerminalErrorData struct {
TerminalCode string `json:"terminal_code,omitempty"`
}
TerminalErrorData JSON-RPC error.data of a failed terminal.* call. terminal_code is the bma.terminal.v1 code the harness relays to the attach (for example terminal_writer_busy).
type TerminalHost ¶
TerminalHost Outbound host socket for one attach. The ticket is a single-use, short-lived bearer credential sent only in the Authorization header, never in the URL.
type TerminalOpenParams ¶
type TerminalOpenParams struct {
TerminalID string `json:"terminal_id"`
// human or agent.
Kind string `json:"kind"`
Shell string `json:"shell,omitempty"`
Argv []string `json:"argv,omitempty"`
Cwd string `json:"cwd,omitempty"`
Env map[string]string `json:"env,omitempty"`
Rows uint16 `json:"rows,omitempty"`
Cols uint16 `json:"cols,omitempty"`
}
TerminalOpenParams is the params object of terminal.open.
type TerminalOpenResult ¶
type TerminalOpenResult struct {
TerminalID string `json:"terminal_id"`
Epoch int64 `json:"epoch"`
PID int `json:"pid"`
Rows uint16 `json:"rows"`
Cols uint16 `json:"cols"`
EarliestSeq int64 `json:"earliest_seq"`
LatestSeq int64 `json:"latest_seq"`
CreatedAt string `json:"created_at"`
}
TerminalOpenResult terminal.open result. epoch starts at 1 and increments when the executor recreates the PTY under the same terminal_id; attach is fenced by it.
type ToolCallParams ¶
type ToolCallParams struct {
SessionID string `json:"session_id"`
ToolCallID string `json:"tool_call_id"`
Tool string `json:"tool"`
Input json.RawMessage `json:"input"`
DeadlineMS int64 `json:"deadline_ms,omitempty"`
Permission *ToolPermission `json:"permission,omitempty"`
}
ToolCallParams is the params object of tool.call.
func (ToolCallParams) DecodeInput ¶
func (p ToolCallParams) DecodeInput() (ToolInput, error)
DecodeInput decodes tool.call input into the built-in ToolInput shape. The wire keeps input raw because each tool defines which members it reads.
type ToolCancelParams ¶
type ToolCancelParams struct {
SessionID string `json:"session_id"`
ToolCallID string `json:"tool_call_id"`
Reason string `json:"reason,omitempty"`
}
ToolCancelParams is the params object of tool.cancel.
type ToolCancelResult ¶
type ToolCancelResult struct {
Canceled bool `json:"canceled"`
}
ToolCancelResult tool.cancel result.
type ToolContext ¶ added in v1.0.0
type ToolContext struct {
SessionID string
ToolCallID string
Permission *ToolPermission
// Progress sends tool.progress for this call (best-effort).
Progress func(message string)
// contains filtered or unexported fields
}
ToolContext describes the call a handler serves.
type ToolError ¶ added in v1.0.0
type ToolError struct {
Content []ContentBlock
}
ToolError is a tool-level error reported to the model (outcome succeeded, is_error true), as Core reports a missing file. Same role as the Anthropic SDK ToolError.
func NewToolError ¶ added in v1.0.0
NewToolError returns a ToolError with one text block.
type ToolInput ¶
type ToolInput struct {
Command string `json:"command,omitempty"`
Cwd string `json:"cwd,omitempty"`
TimeoutMS int64 `json:"timeout_ms,omitempty"`
Env map[string]string `json:"env,omitempty"`
Path string `json:"path,omitempty"`
Offset int64 `json:"offset,omitempty"`
Limit int64 `json:"limit,omitempty"`
Content string `json:"content,omitempty"`
OldString string `json:"old_string,omitempty"`
NewString string `json:"new_string,omitempty"`
Pattern string `json:"pattern,omitempty"`
Glob string `json:"glob,omitempty"`
Display string `json:"display,omitempty"`
Action string `json:"action,omitempty"`
}
ToolInput Superset of every built-in tool input, decoded by executors that read input generically. tool.call selects the exact per-tool schema through x-bma-params-discriminator; unknown members are ignored.
type ToolOutput ¶ added in v1.0.0
type ToolOutput struct {
Content []ContentBlock
IsError bool
Artifacts []ArtifactRef
// Outcome is empty for succeeded; ToolOutcomeCanceled reports a call the
// handler abandoned because ctx was canceled.
Outcome string
}
ToolOutput is a handler's result; the client fills in the ids and duration.
func TextOutput ¶ added in v1.0.0
func TextOutput(text string) ToolOutput
TextOutput is a ToolOutput of one text block.
type ToolPermission ¶
type ToolPermission struct {
Mode string `json:"mode"`
}
ToolPermission Tool permission resolved by the harness.
type ToolProgressParams ¶
type ToolProgressParams struct {
SessionID string `json:"session_id"`
ToolCallID string `json:"tool_call_id"`
Message string `json:"message"`
}
ToolProgressParams is the params object of tool.progress.
type ToolResultParams ¶
type ToolResultParams struct {
SessionID string `json:"session_id"`
ToolCallID string `json:"tool_call_id"`
Outcome string `json:"outcome"`
IsError bool `json:"is_error"`
Content []ContentBlock `json:"content"`
DurationMS int64 `json:"duration_ms,omitempty"`
Artifacts []ArtifactRef `json:"artifacts,omitempty"`
}
ToolResultParams is the params object of tool.result.
type ToolRoute ¶ added in v1.4.0
type ToolRoute interface {
// Call runs one tool call and always answers: a refusal, a transport
// failure or an unclear outcome is a RouteResult with IsError set, never
// a Go error. A repeated Call with the same RouteCall.ID is answered with
// the first result (RouteResult.Replayed), not run again.
Call(ctx context.Context, call RouteCall) *RouteResult
}
ToolRoute is where a brain's tool calls go to run (ADR-0029, brain-hands split): the seam between a brain and its hands. A brain written against the SDK gets the route of its turn from AgentTurn.Tools and never needs to know where the hands are.
There are two routes. PlatformToolRoute is the platform's execute-only tool gateway (ADR-0005): it checks the turn's credential and epoch, re-evaluates the tool policy, verifies the user's approval, runs each call id at most once and runs the tool on the session's hands machine, which may refuse it again by its own policy. LocalToolRoute (the hands are this machine) answers with the same outcomes and refuses for the same reasons with the same error codes. Both are held to the tool route conformance suite (package conformance, cases T1–T11), which a route of your own can run too.
A ToolRoute is bound to one turn of one session and is safe for concurrent use. Its calls end with ctx: a canceled ctx abandons the call, which does not kill a process already started on the hands (the platform's turn cancel does).
type ToolSlot ¶ added in v1.0.0
type ToolSlot[In any] struct { // contains filtered or unexported fields }
ToolSlot serves tool.call for one built-in tool.
func (ToolSlot[In]) Handle ¶ added in v1.0.0
func (s ToolSlot[In]) Handle(handler func(ctx context.Context, input In, tool ToolContext) (ToolOutput, error))
Handle registers the handler of this tool, replacing an earlier one. The shell and files capabilities follow the registered handlers; registering after Start sends executor.capabilities.update, as MCP servers announce tools registered after connecting (tools/list_changed). Input missing a member the contract requires fails the call before the handler runs.
type Tools ¶ added in v1.0.0
type Tools struct {
Bash ToolSlot[BashInput]
Read ToolSlot[ReadInput]
Write ToolSlot[WriteInput]
Edit ToolSlot[EditInput]
Glob ToolSlot[GlobInput]
Grep ToolSlot[GrepInput]
ListFiles ToolSlot[ListFilesInput]
}
Tools has one typed slot per built-in tool: client.Tools.Bash.Handle(...). computer_observe and computer_action have no slot until the contract defines their input members.
type ToolsTokenRefreshParams ¶ added in v1.3.0
type ToolsTokenRefreshParams struct {
// Platform session id of the turn.
SessionID string `json:"session_id"`
// Platform id of the running turn the token is for.
TurnID string `json:"turn_id"`
}
ToolsTokenRefreshParams is the params object of tools_token.refresh.
type ToolsTokenRefreshResult ¶ added in v1.3.0
type ToolsTokenRefreshResult struct {
// Bearer token for tools_mcp_url, bound to the org, session, turn, brain machine and brain epoch of the turn. Valid until expires_at.
ToolsMCPToken string `json:"tools_mcp_token"`
// The session's platform tools endpoint the token is for (https://<executor host>/v1/machines/{brain_machine_id}/mcp).
ToolsMCPURL string `json:"tools_mcp_url"`
// RFC 3339 time the token stops being accepted.
ExpiresAt string `json:"expires_at"`
}
ToolsTokenRefreshResult Contract 1.4.0. tools_token.refresh result: the credential for the turn's next platform tool calls, in the form of the turn.start metadata tools_mcp_url, tools_mcp_token and tools_mcp_token_expires_at.
func SendToolsTokenRefresh ¶ added in v1.3.0
func SendToolsTokenRefresh(ctx context.Context, rpc RPC, params ToolsTokenRefreshParams) (ToolsTokenRefreshResult, error)
SendToolsTokenRefresh calls tools_token.refresh.
type TurnCancelParams ¶
type TurnCancelParams struct {
SessionID string `json:"session_id"`
TurnID string `json:"turn_id"`
Reason string `json:"reason,omitempty"`
}
TurnCancelParams is the params object of turn.cancel.
type TurnCancelResult ¶
type TurnCancelResult struct {
Canceled bool `json:"canceled"`
}
TurnCancelResult turn.cancel result. canceled=false when the turn is unknown or already ended; the turn still ends with its own session.status_idle event.
type TurnInputParams ¶
type TurnInputParams struct {
SessionID string `json:"session_id"`
TurnID string `json:"turn_id"`
InputID string `json:"input_id"`
Input []AgentInputBlock `json:"input"`
}
TurnInputParams is the params object of turn.input.
type TurnStartParams ¶
type TurnStartParams struct {
// Platform session id.
SessionID string `json:"session_id"`
TurnID string `json:"turn_id"`
// Platform input id of the user message that starts the turn.
InputID string `json:"input_id"`
Input []AgentInputBlock `json:"input"`
ExecutorSessionRef string `json:"executor_session_ref,omitempty"`
Config *AgentTurnConfig `json:"config,omitempty"`
DeadlineMS int64 `json:"deadline_ms,omitempty"`
// String key/value pairs the platform adds to the turn. Per-turn credentials the executor declared in AgentCapability.platform_credentials: model_base_url, model_token (and optionally model_context_window, model_max_output_tokens) for harness_model; for brain_tools (contract 1.4.0, only when this machine is the brain and a different machine the hands of the session) tools_mcp_url (https://executor.<domain>/v1/machines/{brain_machine_id}/mcp), tools_mcp_token and tools_mcp_token_expires_at (RFC 3339, 1 hour after turn.start). With tools_mcp_* present every tool call of the turn must go to that endpoint as an MCP tools/call (tools bash, read, write, edit, glob, grep) and none may run on this machine: when the endpoint cannot be reached or refuses the token the call fails and the executor never falls back to running the tool locally (fail closed). The token is bound to the turn's event epoch: the same turn started again after an executor restart (turn.start with the same turn_id, a new epoch) carries a new token and the previous token is refused. Refresh with tools_token.refresh. tool_policy is a JSON object of tool name to allow, ask or deny (for example {"bash":"ask","write":"deny"}): the permission of those tools for this turn, applied over AgentTurnConfig.permission_mode; an executor may only make a tool stricter than its own ceiling, never looser, and a tool the object does not name keeps the mode's permission. Keys the executor does not know are ignored.
Metadata map[string]string `json:"metadata,omitempty"`
}
TurnStartParams is the params object of turn.start.
type TurnStartResult ¶
type TurnStartResult struct {
Accepted bool `json:"accepted"`
TurnID string `json:"turn_id"`
// Opaque local session handle (for example the local agent's conversation id). The platform stores it and sends it back in the next turn.start so the executor can resume the local conversation after a restart.
ExecutorSessionRef string `json:"executor_session_ref"`
// true when the executor continued an existing local conversation, false when it started a new one.
Resumed bool `json:"resumed"`
Effective AgentTurnConfig `json:"effective"`
}
TurnStartResult turn.start result. Idempotent by turn_id: a repeated turn.start for a turn the executor already accepted returns the same result without starting a second run.
type WorkspaceBackupParams ¶
type WorkspaceBackupParams struct {
BackupID string `json:"backup_id"`
Paths []string `json:"paths"`
Exclude []string `json:"exclude,omitempty"`
SkipIfFingerprint string `json:"skip_if_fingerprint,omitempty"`
}
WorkspaceBackupParams is the params object of workspace.backup.
type WorkspaceBackupResult ¶
type WorkspaceBackupResult struct {
State string `json:"state"`
Fingerprint string `json:"fingerprint,omitempty"`
Digest string `json:"digest,omitempty"`
SizeBytes int64 `json:"size_bytes,omitempty"`
Entries int `json:"entries,omitempty"`
Skipped int `json:"skipped,omitempty"`
Error string `json:"error,omitempty"`
}
WorkspaceBackupResult workspace.backup result. digest and size_bytes describe the archive as the server stored it; skipped counts entries that could not be read (missing from the archive).
type WorkspaceCapability ¶
type WorkspaceCapability struct {
Backup bool `json:"backup"`
}
WorkspaceCapability workspace.backup support and the startup restore of a pending backup. Machine-scoped executors only.
type WriteInput ¶ added in v1.0.0
type WriteInput struct {
// File path, relative to the session workspace.
Path string `json:"path"`
// Full file content.
Content string `json:"content"`
}
WriteInput write input: create or replace a file.
Source Files
¶
- agent.go
- agent_acp.go
- agent_acp_claude.go
- agent_acp_host_tools.go
- agent_acp_images.go
- agent_acp_open.go
- agent_acp_proxy.go
- agent_acp_remote.go
- agent_acp_resume.go
- agent_harness.go
- artifact.go
- client.go
- computer_use.go
- core.go
- core_files.go
- core_mounts.go
- daemon.go
- filetransfer.go
- generated.go
- harness.go
- harness_mcp.go
- mcp.go
- methods_gen.go
- npipe.go
- npipe_other.go
- proc_unix.go
- process.go
- reason.go
- replace_other.go
- session_context.go
- session_files.go
- tool_input.go
- toolroute.go
- toolroute_local.go
- toolroute_local_bash.go
- toolroute_platform.go
- tools.go
- transport.go
- typed_methods.go
- wincmdline.go
- winenv.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package conformance is the tool route conformance suite of the SDK (ADR-0029 §5, cases T1–T11), for the tests of anything that is a bmaexecutor.ToolRoute: the SDK's LocalToolRoute and PlatformToolRoute, and the route of a brain or hands of your own.
|
Package conformance is the tool route conformance suite of the SDK (ADR-0029 §5, cases T1–T11), for the tests of anything that is a bmaexecutor.ToolRoute: the SDK's LocalToolRoute and PlatformToolRoute, and the route of a brain or hands of your own. |
|
gatewaystub
Package gatewaystub is a contract double of the platform's execute-only tool gateway (ADR-0005) and of the hands behind it, for tests of brains, of hands and of the SDK's tool routes.
|
Package gatewaystub is a contract double of the platform's execute-only tool gateway (ADR-0005) and of the hands behind it, for tests of brains, of hands and of the SDK's tool routes. |
|
examples
|
|
|
agentexecutor
command
Command agentexecutor is a scripted local agent ("brain and hands" on this machine) served to the platform through the executor SDK's agent capability.
|
Command agentexecutor is a scripted local agent ("brain and hands" on this machine) served to the platform through the executor SDK's agent capability. |
|
cloud-hand
command
Command cloud-hand runs this machine as an executor ("hand") for the BMA cloud harness: the cloud assigns sessions and sends tool calls; the SDK execution core runs bash/file tools and the stdio MCP servers named in session.assign, and reports results back over the same connection.
|
Command cloud-hand runs this machine as an executor ("hand") for the BMA cloud harness: the cloud assigns sessions and sends tool calls; the SDK execution core runs bash/file tools and the stdio MCP servers named in session.assign, and reports results back over the same connection. |
|
echo-mcp
command
Command echo-mcp is a minimal stdio MCP server with one tool, "echo".
|
Command echo-mcp is a minimal stdio MCP server with one tool, "echo". |
|
local-brain
command
Command local-brain is a minimal local harness ("brain") driving the same executor execution core as the cloud, over loopback with the same protocol:
|
Command local-brain is a minimal local harness ("brain") driving the same executor execution core as the cloud, over loopback with the same protocol: |
|
local-dsh
command
Command local-dsh runs a local DSH brain on this computer for BMA: one executor connection (a BYO machine) that hosts bma-dsh-acp over ACP and runs its tools here, in the turn's working directory.
|
Command local-dsh runs a local DSH brain on this computer for BMA: one executor connection (a BYO machine) that hosts bma-dsh-acp over ACP and runs its tools here, in the turn's working directory. |
|
sandboxed-folder
command
Command sandboxed-folder runs this machine as a BMA executor whose processes work in a local folder chosen per session, inside a macOS sandbox-exec profile that only allows writes to that folder and the session's outputs.
|
Command sandboxed-folder runs this machine as a BMA executor whose processes work in a local folder chosen per session, inside a macOS sandbox-exec profile that only allows writes to that folder and the session's outputs. |
|
third-party-brain
command
Command third-party-brain is the smallest brain a third party can write against the SDK and the executor contract alone (ADR-0029): it takes a turn, decides what to do, asks the user's approval, runs the tool wherever the session's hands are, and reports events.
|
Command third-party-brain is the smallest brain a third party can write against the SDK and the executor contract alone (ADR-0029): it takes a turn, decides what to do, asks the user's approval, runs the tool wherever the session's hands are, and reports events. |
|
third-party-hand
command
Command third-party-hand is the smallest "hands" a third party can write against the SDK and the executor contract alone (ADR-0029): this computer registers with BMA, and whichever brain a session binds - on the platform, on another computer, or in a sandbox - uses it to run bash and file tools (read, write, edit, glob, grep) and processes in the session's workspace.
|
Command third-party-hand is the smallest "hands" a third party can write against the SDK and the executor contract alone (ADR-0029): this computer registers with BMA, and whichever brain a session binds - on the platform, on another computer, or in a sandbox - uses it to run bash and file tools (read, write, edit, glob, grep) and processes in the session's workspace. |
|
windows-hand
command
Command windows-hand is the machine executor for a Windows machine ("hand"): the SDK execution core (cmd.exe bash tool, file tools, stdio MCP), the process capability (Job Object process trees, ConPTY terminals, interrupts, file transfers), session files and, when Cua Driver runs in the desktop session, computer use.
|
Command windows-hand is the machine executor for a Windows machine ("hand"): the SDK execution core (cmd.exe bash tool, file tools, stdio MCP), the process capability (Job Object process trees, ConPTY terminals, interrupts, file transfers), session files and, when Cua Driver runs in the desktop session, computer use. |
|
internal
|
|
|
conformance/agentharness
command
Command agentharness is the Go agent-platform peer of the cross-language tests: a Go SDK Harness with an in-memory AgentPlatform that prints "LISTEN <ws-url>", starts one turn ("hello") on the first executor, allows its permission interaction, and expects the durable events session.status_running, agent.message "<language>:hello:allow", session.status_idle (completed) with sequences 1..3.
|
Command agentharness is the Go agent-platform peer of the cross-language tests: a Go SDK Harness with an in-memory AgentPlatform that prints "LISTEN <ws-url>", starts one turn ("hello") on the first executor, allows its permission interaction, and expects the durable events session.status_running, agent.message "<language>:hello:allow", session.status_idle (completed) with sequences 1..3. |
|
conformance/executor
command
Command executor is the Go executor peer of the cross-language tests: a Go SDK Client that dials the harness at os.Args[1] (bearer "conformance"), answers bash with "go:<command>", blocks on the bash command "block" until canceled, echoes MCP frames on server key "echo", and serves an agent that asks for permission, then emits agent.message "go:<first input text>".
|
Command executor is the Go executor peer of the cross-language tests: a Go SDK Client that dials the harness at os.Args[1] (bearer "conformance"), answers bash with "go:<command>", blocks on the bash command "block" until canceled, echoes MCP frames on server key "echo", and serves an agent that asks for permission, then emits agent.message "go:<first input text>". |
|
conformance/harness
command
Command harness is the cross-language conformance peer: a Go SDK Harness that prints "LISTEN <ws-url>", waits for one executor and drives the standard scenario.
|
Command harness is the cross-language conformance peer: a Go SDK Harness that prints "LISTEN <ws-url>", waits for one executor and drives the standard scenario. |
|
interop/goexecutor
command
Command goexecutor is the Go executor peer of the cross-language interop tests (python/tests/test_executor_interop.py).
|
Command goexecutor is the Go executor peer of the cross-language interop tests (python/tests/test_executor_interop.py). |
|
interop/goharness
command
Command goharness is the Go harness peer of the cross-language interop tests (python/tests/test_executor_interop.py).
|
Command goharness is the Go harness peer of the cross-language interop tests (python/tests/test_executor_interop.py). |
|
interop/mcpexecutor
command
Command mcpexecutor is the Go executor peer of the cross-language interop tests (TypeScript and Python).
|
Command mcpexecutor is the Go executor peer of the cross-language interop tests (TypeScript and Python). |
|
interop/mcpharness
command
Command mcpharness is the Go harness peer of the cross-language interop tests (TypeScript and Python).
|
Command mcpharness is the Go harness peer of the cross-language interop tests (TypeScript and Python). |