@openbox-ai/openbox-mastra-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +158 -0
  3. package/dist/client/index.d.ts +4 -0
  4. package/dist/client/index.js +2 -0
  5. package/dist/client/index.js.map +1 -0
  6. package/dist/client/openbox-client.d.ts +42 -0
  7. package/dist/client/openbox-client.js +405 -0
  8. package/dist/client/openbox-client.js.map +1 -0
  9. package/dist/config/index.d.ts +5 -0
  10. package/dist/config/index.js +2 -0
  11. package/dist/config/index.js.map +1 -0
  12. package/dist/config/openbox-config.d.ts +54 -0
  13. package/dist/config/openbox-config.js +162 -0
  14. package/dist/config/openbox-config.js.map +1 -0
  15. package/dist/governance/activity-runtime.d.ts +42 -0
  16. package/dist/governance/activity-runtime.js +712 -0
  17. package/dist/governance/activity-runtime.js.map +1 -0
  18. package/dist/governance/approval-registry.d.ts +17 -0
  19. package/dist/governance/approval-registry.js +32 -0
  20. package/dist/governance/approval-registry.js.map +1 -0
  21. package/dist/governance/context.d.ts +16 -0
  22. package/dist/governance/context.js +13 -0
  23. package/dist/governance/context.js.map +1 -0
  24. package/dist/governance/index.d.ts +2 -0
  25. package/dist/governance/index.js +1 -0
  26. package/dist/governance/index.js.map +1 -0
  27. package/dist/index.d.ts +18 -0
  28. package/dist/index.js +8 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/mastra/index.d.ts +16 -0
  31. package/dist/mastra/index.js +5 -0
  32. package/dist/mastra/index.js.map +1 -0
  33. package/dist/mastra/with-openbox.d.ts +30 -0
  34. package/dist/mastra/with-openbox.js +243 -0
  35. package/dist/mastra/with-openbox.js.map +1 -0
  36. package/dist/mastra/wrap-agent.d.ts +14 -0
  37. package/dist/mastra/wrap-agent.js +1744 -0
  38. package/dist/mastra/wrap-agent.js.map +1 -0
  39. package/dist/mastra/wrap-tool.d.ts +18 -0
  40. package/dist/mastra/wrap-tool.js +49 -0
  41. package/dist/mastra/wrap-tool.js.map +1 -0
  42. package/dist/mastra/wrap-workflow.d.ts +14 -0
  43. package/dist/mastra/wrap-workflow.js +386 -0
  44. package/dist/mastra/wrap-workflow.js.map +1 -0
  45. package/dist/otel/index.d.ts +11 -0
  46. package/dist/otel/index.js +2 -0
  47. package/dist/otel/index.js.map +1 -0
  48. package/dist/otel/setup-openbox-opentelemetry.d.ts +38 -0
  49. package/dist/otel/setup-openbox-opentelemetry.js +2249 -0
  50. package/dist/otel/setup-openbox-opentelemetry.js.map +1 -0
  51. package/dist/span/index.d.ts +5 -0
  52. package/dist/span/index.js +2 -0
  53. package/dist/span/index.js.map +1 -0
  54. package/dist/span/openbox-span-processor.d.ts +90 -0
  55. package/dist/span/openbox-span-processor.js +580 -0
  56. package/dist/span/openbox-span-processor.js.map +1 -0
  57. package/dist/types/errors.d.ts +25 -0
  58. package/dist/types/errors.js +40 -0
  59. package/dist/types/errors.js.map +1 -0
  60. package/dist/types/governance-verdict-response.d.ts +57 -0
  61. package/dist/types/governance-verdict-response.js +84 -0
  62. package/dist/types/governance-verdict-response.js.map +1 -0
  63. package/dist/types/guardrails.d.ts +23 -0
  64. package/dist/types/guardrails.js +27 -0
  65. package/dist/types/guardrails.js.map +1 -0
  66. package/dist/types/index.d.ts +6 -0
  67. package/dist/types/index.js +7 -0
  68. package/dist/types/index.js.map +1 -0
  69. package/dist/types/verdict.d.ts +22 -0
  70. package/dist/types/verdict.js +55 -0
  71. package/dist/types/verdict.js.map +1 -0
  72. package/dist/types/workflow-event-type.d.ts +10 -0
  73. package/dist/types/workflow-event-type.js +13 -0
  74. package/dist/types/workflow-event-type.js.map +1 -0
  75. package/dist/types/workflow-span-buffer.d.ts +31 -0
  76. package/dist/types/workflow-span-buffer.js +42 -0
  77. package/dist/types/workflow-span-buffer.js.map +1 -0
  78. package/docs/README.md +66 -0
  79. package/docs/api-reference.md +348 -0
  80. package/docs/approvals-and-guardrails.md +163 -0
  81. package/docs/architecture.md +186 -0
  82. package/docs/configuration.md +214 -0
  83. package/docs/event-model.md +215 -0
  84. package/docs/installation.md +108 -0
  85. package/docs/integration-patterns.md +214 -0
  86. package/docs/security-and-privacy.md +174 -0
  87. package/docs/telemetry.md +196 -0
  88. package/docs/troubleshooting.md +210 -0
  89. package/package.json +136 -0
@@ -0,0 +1,348 @@
1
+ # API Reference
2
+
3
+ This document summarizes the public API exported by `@openbox-ai/openbox-mastra-sdk`.
4
+
5
+ It is an integration-focused reference, not a generated type reference. Use it to decide which module to import from and which entrypoints the SDK expects you to use.
6
+
7
+ ## Recommended Imports
8
+
9
+ Most applications should import from the package root:
10
+
11
+ ```ts
12
+ import {
13
+ getOpenBoxRuntime,
14
+ withOpenBox
15
+ } from "@openbox-ai/openbox-mastra-sdk";
16
+ ```
17
+
18
+ Use subpath imports only when you want to make module ownership explicit:
19
+
20
+ - `@openbox-ai/openbox-mastra-sdk/client`
21
+ - `@openbox-ai/openbox-mastra-sdk/config`
22
+ - `@openbox-ai/openbox-mastra-sdk/mastra`
23
+ - `@openbox-ai/openbox-mastra-sdk/otel`
24
+ - `@openbox-ai/openbox-mastra-sdk/span`
25
+ - `@openbox-ai/openbox-mastra-sdk/types`
26
+
27
+ The `./governance` subpath exists, but it does not currently expose a public API surface of its own.
28
+
29
+ ## Root Export Families
30
+
31
+ The root module re-exports:
32
+
33
+ - client
34
+ - config
35
+ - mastra integration
36
+ - telemetry
37
+ - span processing
38
+ - public types
39
+
40
+ ## Client Module
41
+
42
+ Import path:
43
+
44
+ ```ts
45
+ import { OpenBoxClient } from "@openbox-ai/openbox-mastra-sdk";
46
+ ```
47
+
48
+ ### `type OpenBoxApiErrorPolicy`
49
+
50
+ ```ts
51
+ type OpenBoxApiErrorPolicy = "fail_open" | "fail_closed";
52
+ ```
53
+
54
+ Controls how API failures are treated.
55
+
56
+ ### `interface OpenBoxClientOptions`
57
+
58
+ Key fields:
59
+
60
+ - `apiKey`
61
+ - `apiUrl`
62
+ - `evaluateMaxRetries`
63
+ - `evaluateRetryBaseDelayMs`
64
+ - `fetch`
65
+ - `onApiError`
66
+ - `timeoutSeconds`
67
+
68
+ ### `class OpenBoxClient`
69
+
70
+ Main methods:
71
+
72
+ - `validateApiKey(): Promise<void>`
73
+ - `evaluate(payload): Promise<GovernanceVerdictResponse | null>`
74
+ - `pollApproval(payload): Promise<ApprovalPollResponse | null>`
75
+
76
+ Use this class when you need explicit control over transport, retries, or approval polling.
77
+
78
+ ## Config Module
79
+
80
+ Import path:
81
+
82
+ ```ts
83
+ import {
84
+ API_KEY_PATTERN,
85
+ getOpenBoxConfig,
86
+ initializeOpenBox,
87
+ parseOpenBoxConfig,
88
+ setOpenBoxConfig,
89
+ validateApiKeyFormat,
90
+ validateUrlSecurity
91
+ } from "@openbox-ai/openbox-mastra-sdk";
92
+ ```
93
+
94
+ ### `interface OpenBoxConfigInput`
95
+
96
+ User-supplied config surface. See [configuration.md](./configuration.md) for the complete option table.
97
+
98
+ ### `interface OpenBoxConfig`
99
+
100
+ Normalized runtime config with defaults applied and iterable fields converted to `Set<string>`.
101
+
102
+ ### `parseOpenBoxConfig(input?, env?)`
103
+
104
+ Parses:
105
+
106
+ - explicit config options
107
+ - environment variables
108
+
109
+ Performs:
110
+
111
+ - required field checks
112
+ - API key format validation
113
+ - URL security validation
114
+ - default filling
115
+
116
+ ### `initializeOpenBox(input?)`
117
+
118
+ Parses config and, if validation is enabled, validates the API key against OpenBox Core.
119
+
120
+ Use it when:
121
+
122
+ - you want config initialized before wiring wrappers
123
+ - you want startup validation separate from `withOpenBox()`
124
+
125
+ ### `getOpenBoxConfig()` and `setOpenBoxConfig()`
126
+
127
+ Access or override the global config singleton.
128
+
129
+ Use sparingly. Prefer explicit runtime injection where practical.
130
+
131
+ ## Mastra Module
132
+
133
+ Import path:
134
+
135
+ ```ts
136
+ import {
137
+ getOpenBoxRuntime,
138
+ withOpenBox,
139
+ wrapAgent,
140
+ wrapTool,
141
+ wrapWorkflow
142
+ } from "@openbox-ai/openbox-mastra-sdk";
143
+ ```
144
+
145
+ ### `interface WrapToolOptions`
146
+
147
+ Shared dependency bag used by wrappers:
148
+
149
+ - `client`
150
+ - `config`
151
+ - `spanProcessor`
152
+
153
+ ### `wrapTool(tool, options)`
154
+
155
+ Wraps a Mastra tool in governed activity execution.
156
+
157
+ Typical effects:
158
+
159
+ - boundary activity events
160
+ - verdict enforcement
161
+ - guardrail handling
162
+ - approval handling
163
+ - telemetry association
164
+
165
+ ### `wrapWorkflow(workflow, options)`
166
+
167
+ Wraps workflow lifecycle and non-tool workflow steps.
168
+
169
+ Typical effects:
170
+
171
+ - workflow start, completion, and failure events
172
+ - resume signal events
173
+ - governed step execution
174
+
175
+ ### `wrapAgent(agent, options)`
176
+
177
+ Wraps agent lifecycle.
178
+
179
+ Typical effects:
180
+
181
+ - workflow-like lifecycle events for the agent run
182
+ - `user_input`, `resume`, and `agent_output` signals
183
+ - agent goal propagation
184
+ - agent-only LLM spans routed through signal telemetry
185
+
186
+ ### `interface WithOpenBoxOptions`
187
+
188
+ Extends `OpenBoxConfigInput` and adds:
189
+
190
+ - `client`
191
+ - `dbLibraries`
192
+ - `fetch`
193
+ - `fileSkipPatterns`
194
+ - `ignoredUrls`
195
+ - `spanProcessor`
196
+
197
+ ### `interface OpenBoxRuntime`
198
+
199
+ Runtime returned indirectly by `withOpenBox()` and accessible via `getOpenBoxRuntime()`.
200
+
201
+ Fields:
202
+
203
+ - `client`
204
+ - `config`
205
+ - `spanProcessor`
206
+ - `telemetry`
207
+ - `shutdown()`
208
+
209
+ ### `withOpenBox(target, options?)`
210
+
211
+ Recommended zero-code integration.
212
+
213
+ Accepts:
214
+
215
+ - a Mastra instance
216
+ - an object containing `.mastra`
217
+
218
+ Creates runtime, patches Mastra, installs telemetry, and returns the same logical target.
219
+
220
+ ### `getOpenBoxRuntime(target)`
221
+
222
+ Returns the installed runtime when available. Use it for:
223
+
224
+ - shutdown
225
+ - access to normalized config
226
+ - direct access to the client or span processor
227
+
228
+ ## Telemetry Module
229
+
230
+ Import path:
231
+
232
+ ```ts
233
+ import {
234
+ setupOpenBoxOpenTelemetry,
235
+ traced
236
+ } from "@openbox-ai/openbox-mastra-sdk";
237
+ ```
238
+
239
+ ### `interface OpenBoxTelemetryOptions`
240
+
241
+ Fields:
242
+
243
+ - `spanProcessor`
244
+ - `governanceClient`
245
+ - `captureHttpBodies`
246
+ - `dbLibraries`
247
+ - `fileSkipPatterns`
248
+ - `ignoredUrls`
249
+ - `instrumentDatabases`
250
+ - `instrumentFileIo`
251
+ - `onHookApiError`
252
+
253
+ ### `interface OpenBoxTelemetryController`
254
+
255
+ Fields:
256
+
257
+ - `instrumentations`
258
+ - `tracerProvider`
259
+ - `shutdown()`
260
+
261
+ ### `setupOpenBoxOpenTelemetry(options)`
262
+
263
+ Installs the SDK's process-wide telemetry layer.
264
+
265
+ Use it directly when:
266
+
267
+ - you are not using `withOpenBox()`
268
+ - you need explicit bootstrap order
269
+ - you only want telemetry without full Mastra patching
270
+
271
+ ### `interface OpenBoxTracedOptions`
272
+
273
+ Fields:
274
+
275
+ - `captureArgs`
276
+ - `captureResult`
277
+ - `module`
278
+ - `name`
279
+ - `tracerName`
280
+
281
+ ### `traced(fn, options?)`
282
+
283
+ Wraps an async function in a traced function span.
284
+
285
+ Use it for:
286
+
287
+ - custom operations outside standard tool or workflow boundaries
288
+ - explicitly named operational spans
289
+ - additional policy-relevant function telemetry
290
+
291
+ ## Span Module
292
+
293
+ Import path:
294
+
295
+ ```ts
296
+ import { OpenBoxSpanProcessor } from "@openbox-ai/openbox-mastra-sdk";
297
+ ```
298
+
299
+ ### `class OpenBoxSpanProcessor`
300
+
301
+ Implements the OpenTelemetry `SpanProcessor` interface and manages the SDK's enriched governance span buffer.
302
+
303
+ Typical usage:
304
+
305
+ - pass it to `setupOpenBoxOpenTelemetry()`
306
+ - reuse it across wrappers
307
+ - let `withOpenBox()` create it unless you need manual control
308
+
309
+ Exported companion types:
310
+
311
+ - `StoredSpanBody`
312
+ - `StoredTraceBody`
313
+ - `StoredWorkflowVerdict`
314
+ - `OpenBoxSpanData`
315
+ - `OpenBoxSpanProcessorOptions`
316
+ - `WorkflowSpanProcessor` as an alias of `OpenBoxSpanProcessor`
317
+
318
+ ## Types Module
319
+
320
+ Import path:
321
+
322
+ ```ts
323
+ import {
324
+ ApprovalExpiredError,
325
+ ApprovalPendingError,
326
+ ApprovalRejectedError,
327
+ GovernanceAPIError,
328
+ GovernanceVerdictResponse,
329
+ GovernanceHaltError,
330
+ GuardrailsCheckResult,
331
+ GuardrailsValidationError,
332
+ OpenBoxAuthError,
333
+ OpenBoxConfigError,
334
+ OpenBoxError,
335
+ OpenBoxInsecureURLError,
336
+ OpenBoxNetworkError,
337
+ Verdict,
338
+ WorkflowEventType,
339
+ WorkflowSpanBuffer
340
+ } from "@openbox-ai/openbox-mastra-sdk";
341
+ ```
342
+
343
+ Use the exported types for:
344
+
345
+ - explicit error handling
346
+ - verdict inspection
347
+ - workflow event matching
348
+ - testing and integration typing
@@ -0,0 +1,163 @@
1
+ # Approvals And Guardrails
2
+
3
+ This document explains how OpenBox verdicts are enforced by the SDK and how guardrails behave in live runs.
4
+
5
+ ## Verdicts
6
+
7
+ The SDK understands these primary verdicts:
8
+
9
+ | Verdict | Meaning | Runtime effect |
10
+ | --- | --- | --- |
11
+ | `allow` | continue normally | execution proceeds |
12
+ | `constrain` | continue with advisory constraints | execution proceeds and constraints remain available in the response |
13
+ | `require_approval` | human review required | execution suspends or polls for approval |
14
+ | `block` | operation must not continue | execution throws a stop-style error |
15
+ | `halt` | workflow or agent run must stop | execution throws a halt error |
16
+
17
+ Legacy action strings such as `continue`, `stop`, and `require-approval` are normalized into these verdicts.
18
+
19
+ ## Enforcement Model
20
+
21
+ The SDK enforces verdicts at boundary events.
22
+
23
+ For governed activities:
24
+
25
+ 1. `ActivityStarted` is evaluated first
26
+ 2. input-side guardrail handling may apply
27
+ 3. the underlying tool or step executes
28
+ 4. `ActivityCompleted` is evaluated
29
+ 5. output-side guardrail handling may apply
30
+ 6. approval may be required on either side
31
+
32
+ For workflows and agents:
33
+
34
+ - `WorkflowStarted` can stop execution early
35
+ - `WorkflowCompleted` can still be evaluated for policy and telemetry
36
+ - `WorkflowFailed` records failure context
37
+
38
+ ## Important Live-Run Behavior
39
+
40
+ In a standard OpenBox Core deployment, policy evaluates before guardrails for an event.
41
+
42
+ Operational consequence:
43
+
44
+ - if policy returns a non-`allow` verdict such as `require_approval`, `block`, or `halt`, guardrails for that event may not run
45
+ - if you are testing a guardrail live and it does not fire, inspect the policy verdict first
46
+
47
+ This is the most common reason a guardrail UI test passes while the live run still shows no guardrail result.
48
+
49
+ ## Guardrail Input And Output Handling
50
+
51
+ OpenBox responses may contain `guardrails_result`.
52
+
53
+ The SDK uses it in two ways.
54
+
55
+ ### Input Redaction
56
+
57
+ If the response for `ActivityStarted` includes:
58
+
59
+ - `guardrails_result.input_type = "activity_input"`
60
+ - `guardrails_result.redacted_input`
61
+
62
+ the SDK applies the redacted input before calling the underlying tool or step.
63
+
64
+ ### Output Redaction
65
+
66
+ If the response for `ActivityCompleted` includes:
67
+
68
+ - `guardrails_result.input_type = "activity_output"`
69
+ - `guardrails_result.redacted_input`
70
+
71
+ the SDK applies that redacted output before returning it to the caller.
72
+
73
+ ### Validation Failure
74
+
75
+ If `guardrails_result.validation_passed` is `false`, the SDK throws `GuardrailsValidationError`.
76
+
77
+ ## Guardrail Field Selection Guidance
78
+
79
+ For live activity guardrails, match against `ActivityStarted` fields whenever possible.
80
+
81
+ Recommended field targets:
82
+
83
+ | Activity type | Field to check | Example use |
84
+ | --- | --- | --- |
85
+ | `writeFile` | `input.content` | banned content or PII in file contents |
86
+ | `writeFile` | `input.path` | path-based restrictions |
87
+ | `runCommand` | `input.command` | banned shell commands |
88
+
89
+ Important:
90
+
91
+ - agent prompts are emitted as `SignalReceived(user_input)`, not as `ActivityStarted`
92
+ - if your OpenBox deployment only evaluates guardrails on activity events, a `user_input` guardrail will not inspect agent prompts directly
93
+
94
+ ## Human Approval Flow
95
+
96
+ The approval path depends on where execution is happening.
97
+
98
+ ### Workflow-Backed Activity Execution
99
+
100
+ When a tool or step executes inside a workflow context and OpenBox returns `require_approval`:
101
+
102
+ - the SDK creates approval state
103
+ - the workflow suspends through Mastra suspend or resume behavior
104
+ - approval context is stored in the approval registry
105
+ - later resume paths emit `SignalReceived` and poll approval status
106
+
107
+ This is the preferred path for long-running human review.
108
+
109
+ ### Non-Workflow Activity Execution
110
+
111
+ When there is no workflow suspend context available, the SDK polls approval inline.
112
+
113
+ Current inline polling characteristics:
114
+
115
+ - total timeout: 5 minutes
116
+ - initial poll interval: 2.5 seconds
117
+ - exponential backoff up to 15 seconds
118
+
119
+ If approval does not resolve in time, the SDK throws `ApprovalPendingError`.
120
+
121
+ ## Approval Outcomes
122
+
123
+ While polling approval status:
124
+
125
+ - `allow` marks the activity approved and execution continues
126
+ - `block` or `halt` throws `ApprovalRejectedError`
127
+ - expired approval throws `ApprovalExpiredError`
128
+ - missing or temporary approval API failures retry with backoff until timeout
129
+
130
+ ## Output-Time Approval
131
+
132
+ Approval is not limited to `ActivityStarted`.
133
+
134
+ If `ActivityCompleted` returns `require_approval`, the SDK can:
135
+
136
+ - suspend the workflow after execution and before returning output
137
+ - or poll inline when no workflow suspension context exists
138
+
139
+ This is useful when policy wants to review actual output, not just the requested action.
140
+
141
+ ## Agents And Approval
142
+
143
+ Wrapped agents also participate in approval handling through their workflow-like lifecycle.
144
+
145
+ Because agent runs emit `user_input`, `resume`, and `agent_output`, approval state can be resumed consistently across retries or resume calls.
146
+
147
+ ## Runtime Errors You Should Expect
148
+
149
+ | Error | Meaning |
150
+ | --- | --- |
151
+ | `GovernanceHaltError` | OpenBox returned a stop or halt verdict, or a fail-closed API failure was converted into a halt |
152
+ | `GuardrailsValidationError` | guardrail validation failed |
153
+ | `ApprovalPendingError` | approval is still pending or inline polling timed out |
154
+ | `ApprovalRejectedError` | approval explicitly rejected the activity |
155
+ | `ApprovalExpiredError` | approval expired before resolution |
156
+
157
+ ## Production Recommendations
158
+
159
+ 1. Keep approval policy focused on business boundary events.
160
+ 2. Treat hook-triggered telemetry as internal by default.
161
+ 3. When testing guardrails live, make sure policy returns `allow` for that event.
162
+ 4. Use `ActivityStarted` field selectors for tool-input guardrails.
163
+ 5. Do not rely on `SignalReceived(user_input)` guardrails unless your OpenBox deployment explicitly supports guardrails on signals.
@@ -0,0 +1,186 @@
1
+ # Architecture
2
+
3
+ This document explains how the SDK is structured so you can reason about deployment behavior, ownership, and operational tradeoffs.
4
+
5
+ ## Design Goals
6
+
7
+ The SDK is built around four goals:
8
+
9
+ 1. keep governance decisions at clear business boundaries
10
+ 2. attach operational telemetry to those boundaries without building a custom tracing layer
11
+ 3. preserve approval state across workflow and agent resume paths
12
+ 4. make the default integration path safe enough for production bootstrap
13
+
14
+ ## High-Level Layout
15
+
16
+ ```text
17
+ Mastra application
18
+ |- tools
19
+ |- workflows
20
+ `- agents
21
+ |
22
+ v
23
+ OpenBox Mastra SDK
24
+ |- Mastra wrappers
25
+ | |- wrapTool()
26
+ | |- wrapWorkflow()
27
+ | |- wrapAgent()
28
+ | `- withOpenBox()
29
+ |- Governance runtime
30
+ | |- OpenBoxClient
31
+ | |- config parsing
32
+ | `- approval registry
33
+ |- Telemetry runtime
34
+ | |- OpenBoxSpanProcessor
35
+ | |- OpenTelemetry instrumentation
36
+ | `- hook-governance bridge
37
+ `- Public type surface
38
+ |- verdicts
39
+ |- guardrails
40
+ |- workflow events
41
+ `- runtime errors
42
+ |
43
+ v
44
+ OpenBox Core
45
+ |- /api/v1/auth/validate
46
+ |- /api/v1/governance/evaluate
47
+ `- /api/v1/governance/approval
48
+ ```
49
+
50
+ ## Main Runtime Components
51
+
52
+ ### `withOpenBox()`
53
+
54
+ Responsibilities:
55
+
56
+ - create the OpenBox runtime
57
+ - install process-wide telemetry
58
+ - patch current and future Mastra registries
59
+ - expose a runtime handle for shutdown and diagnostics
60
+
61
+ Operational implication:
62
+
63
+ - one governed Mastra process should normally have one active OpenBox runtime
64
+
65
+ ### `OpenBoxClient`
66
+
67
+ Responsibilities:
68
+
69
+ - validate the API key
70
+ - send evaluate requests
71
+ - poll approval status
72
+ - apply retry and timeout policy
73
+ - summarize debug logging when `OPENBOX_DEBUG=true`
74
+
75
+ Operational implication:
76
+
77
+ - API failure behavior is controlled centrally through `onApiError`
78
+
79
+ ### `OpenBoxSpanProcessor`
80
+
81
+ Responsibilities:
82
+
83
+ - buffer spans by workflow and run
84
+ - associate child telemetry with parent activity or workflow context
85
+ - hold captured HTTP bodies and headers until governance payload assembly
86
+ - queue agent-only LLM telemetry until the `agent_output` signal is emitted
87
+
88
+ Operational implication:
89
+
90
+ - telemetry is enriched inside the SDK before it becomes an OpenBox governance payload
91
+
92
+ ### Approval Registry
93
+
94
+ Responsibilities:
95
+
96
+ - track approval state across resume paths
97
+ - keep workflow-backed approval flows coherent
98
+ - prevent approval handling from being tied only to a single stack frame
99
+
100
+ Operational implication:
101
+
102
+ - approval state is runtime control data, not a persistence layer
103
+
104
+ ## Boundary And Telemetry Model
105
+
106
+ The SDK distinguishes between two kinds of data:
107
+
108
+ - business boundary events such as `ActivityStarted`, `ActivityCompleted`, and workflow lifecycle events
109
+ - internal operational telemetry such as HTTP, database, file, and traced-function spans
110
+
111
+ This distinction matters because:
112
+
113
+ - policy is usually easiest to reason about at business boundaries
114
+ - hook-triggered telemetry can be noisy if treated as a second user action
115
+ - approvals become harder to operate if both layers are governed the same way
116
+
117
+ ## Execution Flows
118
+
119
+ ### Tool Or Step Execution
120
+
121
+ ```text
122
+ boundary starts
123
+ -> ActivityStarted
124
+ -> verdict and guardrail handling
125
+ -> underlying execution
126
+ -> telemetry capture during execution
127
+ -> ActivityCompleted
128
+ -> output verdict and guardrail handling
129
+ -> return or suspend
130
+ ```
131
+
132
+ ### Workflow Execution
133
+
134
+ ```text
135
+ workflow starts
136
+ -> WorkflowStarted
137
+ -> governed steps run
138
+ -> optional SignalReceived on resume
139
+ -> WorkflowCompleted or WorkflowFailed
140
+ ```
141
+
142
+ ### Agent Execution
143
+
144
+ ```text
145
+ agent run starts
146
+ -> WorkflowStarted
147
+ -> SignalReceived(user_input)
148
+ -> underlying agent execution
149
+ -> agent LLM and hook telemetry captured
150
+ -> SignalReceived(agent_output)
151
+ -> WorkflowCompleted or WorkflowFailed
152
+ ```
153
+
154
+ ## Why Signals Matter
155
+
156
+ Signals are not just a workflow resume mechanism in this SDK. They also carry agent-specific lifecycle state.
157
+
158
+ Production implications:
159
+
160
+ - agent prompt input is emitted as `SignalReceived(user_input)`
161
+ - agent output and agent-only LLM spans are emitted through `SignalReceived(agent_output)`
162
+ - if you suppress or ignore those signals, you lose the main observability path for agent-level prompt and completion context
163
+
164
+ ## Telemetry Ownership
165
+
166
+ `setupOpenBoxOpenTelemetry()` manages one active telemetry controller per process.
167
+
168
+ Operational implications:
169
+
170
+ - initializing telemetry twice replaces the previous controller
171
+ - shutdown should happen during process termination
172
+ - the OpenBox API URL should be ignored to avoid tracing and governing the SDK's own API traffic
173
+
174
+ ## Failure Model
175
+
176
+ The SDK treats these as distinct classes of failure:
177
+
178
+ - OpenBox API failure
179
+ - governance stop or halt verdict
180
+ - approval pending, rejected, or expired
181
+ - guardrail validation failure
182
+ - underlying tool, workflow, or agent failure
183
+
184
+ Those differences are preserved in the surfaced runtime errors so application code can respond intentionally.
185
+
186
+ See [approvals-and-guardrails.md](./approvals-and-guardrails.md) for enforcement details and [troubleshooting.md](./troubleshooting.md) for common failure modes.