Skip to main content
Last updated on

Configuration

@openbox-ai/openbox-copilotkit can be configured through OPENBOX_* environment variables or explicit options passed to withOpenBoxRuntime(), createOpenBoxMiddleware(), OpenBoxClient, and parseOpenBoxConfig().

Most applications should use withOpenBoxRuntime(options, config).

Configuration Precedence

Configuration is resolved in this order:

  1. Explicit options passed in code
  2. Environment variables
  3. SDK defaults for optional fields

Runtime governance requires an OpenBox Core URL and an agent runtime key.

Required Environment Variables

VariableRequiredDefaultPurpose
OPENBOX_URLYes-OpenBox Core base URL
OPENBOX_API_KEYYes-Agent runtime key, obx_live_* or obx_test_*
OPENBOX_AGENT_DIDWhen signing is enabled-DID assigned to this OpenBox agent
OPENBOX_AGENT_PRIVATE_KEYWhen signing is enabled-Base64 raw Ed25519 private key

Newly created OpenBox agents require DID signing by default. If Require signing is disabled for the registered agent, omit both DID values.

.env.local
OPENBOX_URL=https://core.openbox.ai
OPENBOX_API_KEY=obx_live_or_obx_test_agent_runtime_key
OPENBOX_AGENT_DID=did:aip:550e8400-e29b-41d4-a716-446655440000
OPENBOX_AGENT_PRIVATE_KEY=base64_raw_ed25519_private_key

Optional Environment Variables

VariableDefaultPurpose
OPENBOX_GOVERNANCE_POLICYfail_openmaps to onApiError; use fail_closed to throw when OpenBox is unavailable
OPENBOX_GOVERNANCE_TIMEOUT30OpenBox request timeout in seconds
OPENBOX_EVALUATE_MAX_RETRIES2retry count for governance evaluation
OPENBOX_EVALUATE_RETRY_BASE_DELAY_MS150base backoff delay for evaluate retries
OPENBOX_MAX_EVALUATE_PAYLOAD_BYTES256000maximum governance payload size before validation rejects
OPENBOX_VALIDATEtruevalidate OpenBox credentials at initialization when using config validation
OPENBOX_DEBUGoffenables SDK debug logging in the OpenBox client
OPENBOX_SPAN_BUFFER_MAX_PER_WORKFLOW1000per-workflow cap for optional synthesized tool spans
OPENBOX_SPAN_BUFFER_TTL_MS300000retention TTL for optional synthesized tool spans
OPENBOX_DISABLE_SPAN_BUFFERoffset to 1 to skip optional span synthesis

The config parser also accepts compatibility fields such as OPENBOX_SKIP_ACTIVITY_TYPES, OPENBOX_SKIP_SIGNALS, and OPENBOX_SKIP_WORKFLOW_TYPES, but the CopilotKit Runtime v2 integration usually does not need them.

withOpenBoxRuntime()

import { withOpenBoxRuntime } from "@openbox-ai/openbox-copilotkit";

const { runtime, shutdown } = await withOpenBoxRuntime(
copilotRuntimeOptions,
{
apiKey: process.env.OPENBOX_API_KEY,
apiUrl: process.env.OPENBOX_URL,
agentDid: process.env.OPENBOX_AGENT_DID,
agentPrivateKey: process.env.OPENBOX_AGENT_PRIVATE_KEY,
onApiError: "fail_open",
middlewareOptions: {
frontendToolNames: ["setThemeColor"],
enforceApprovals: false,
},
},
);

The first argument is CopilotRuntimeOptions, not a constructed CopilotRuntime.

Wrapper Config Fields

FieldDefaultPurpose
apiKeyOPENBOX_API_KEYOpenBox agent runtime key
apiUrlOPENBOX_URLOpenBox Core base URL
agentDidOPENBOX_AGENT_DIDDID used for signed OpenBox requests
agentPrivateKeyOPENBOX_AGENT_PRIVATE_KEYEd25519 private key used with the DID
onApiErrorOPENBOX_GOVERNANCE_POLICY or fail_openfail_open returns null on API failure; fail_closed throws
governanceTimeout30OpenBox request timeout in seconds
evaluateMaxRetries2 through parsed configretry count for governance evaluation
evaluateRetryBaseDelayMs150base retry delay
defaults{}fallback agentId, tenantId, and workflowType when request context is absent
loggerconsoleconsole-style sink for SDK warnings and debug logs
middlewareOptions{}options passed to each OpenBox AG-UI middleware instance

Middleware Options

middlewareOptions controls the AG-UI stream observer.

OptionDefaultPurpose
enforceApprovalsfalsewhen true, block or halt verdicts stop the AG-UI stream after tool-call input is known
frontendToolNamesunsetexplicit allowlist for React/frontend tool names that should record frontend: true
isFrontendToolunsetcallback alternative to frontendToolNames; wins when both are set
onEventunsetobserver callback for every OpenBox emission
multiAgentdisabledenables multi_agent_session_id stamping and mapped handoff emission
spanBufferunsetoptional SpanBuffer for synthesized function_call spans
redactPathsunsetJSONPath-like paths to redact from optional span previews

Frontend Tool Labelling

The SDK does not infer which tools originated in React. Add an explicit allowlist:

const { runtime } = await withOpenBoxRuntime(options, {
middlewareOptions: {
frontendToolNames: ["setThemeColor", "showSnackbar"],
},
});

For dynamic registries:

const frontendTools = new Set(["setThemeColor", "showSnackbar"]);

const { runtime } = await withOpenBoxRuntime(options, {
middlewareOptions: {
isFrontendTool: ({ name }) => frontendTools.has(name),
},
});

Unlisted tools record frontend: false and tool_origin: "copilotkit-observed".

Enforcement Policy

Default behavior is telemetry-only:

middlewareOptions: {
enforceApprovals: false,
}

When enforceApprovals: true, the SDK awaits the OpenBox verdict after complete tool-call args are available. Block or halt verdicts stop the stream with this redacted AG-UI error frame:

{
"type": "RUN_ERROR",
"code": "governance_blocked",
"correlationId": "<governanceEventId or approvalId>"
}

The client does not receive the tool name, tenant id, agent id, or verdict reason.

Multi-Agent Options

Enable multi-agent mode only when a CopilotKit tool delegates to a distinct child agent and you want one grouped OpenBox timeline.

const { runtime } = await withOpenBoxRuntime(options, {
agentDid: process.env.OPENBOX_COPILOTKIT_AGENT_DID,
agentPrivateKey: process.env.OPENBOX_COPILOTKIT_AGENT_PRIVATE_KEY,
middlewareOptions: {
multiAgent: {
enabled: true,
parentAgentDid: process.env.OPENBOX_COPILOTKIT_AGENT_DID,
multiAgentSessionId: (ctx) => `mas:${ctx.runId}`,
handoffTools: {
weatherTool: {
childAgentName: "mastra-weather-agent",
childWorkflowType: "weather-agent",
childTaskQueue: "mastra",
childApiKey: process.env.OPENBOX_MASTRA_API_KEY,
childAgentDid: process.env.OPENBOX_MASTRA_AGENT_DID,
childAgentPrivateKey:
process.env.OPENBOX_MASTRA_AGENT_PRIVATE_KEY,
},
},
forwardContext: (ctx) => {
pendingChildContext.set(ctx.parentActivityId, ctx);
return { correlation_id: ctx.parentActivityId };
},
},
},
});
FieldPurpose
enabledopt into multi-agent behavior
parentAgentDidDID used as from_agent_did; falls back to runtime agentDid
multiAgentSessionIdstring or resolver; defaults to mas:${runId}
handoffToolsstatic delegate tool to child agent map
resolveHandoffdynamic delegate resolver
forwardContextapp-owned bridge for passing OpenBoxMultiAgentContext to the child runtime

If child credentials are present, the SDK sends the Handoff request authenticated as the child. If they are absent, it surfaces the prepared handoff payload through onEvent so a remote child runtime can emit the handoff itself.

The child runtime still needs the same multi_agent_session_id and parent_workflow_id; forwarding that context is application glue, not automatic global state.

DID Signing

When agentDid and agentPrivateKey are configured, the SDK signs OpenBox requests with:

HeaderPurpose
X-OpenBox-Agent-DIDagent DID
X-OpenBox-Agent-TimestampUnix timestamp
X-OpenBox-Agent-Noncereplay-prevention nonce
X-OpenBox-Body-SHA256body hash
X-OpenBox-Agent-SignatureEd25519 signature

Configure both DID values together. Partial DID configuration throws during config parsing.

Next Steps