modus-sdk 0.2.0__py3-none-any.whl

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 (98) hide show
  1. modus/__init__.py +144 -0
  2. modus/_auth.py +111 -0
  3. modus/_chat.py +411 -0
  4. modus/_client.py +240 -0
  5. modus/_config.py +89 -0
  6. modus/_deprecation.py +29 -0
  7. modus/_exceptions.py +149 -0
  8. modus/_generated/__init__.py +341 -0
  9. modus/_generated/models.py +3182 -0
  10. modus/_generated/operations.py +891 -0
  11. modus/_http.py +471 -0
  12. modus/_openapi_invoke.py +137 -0
  13. modus/_pagination.py +175 -0
  14. modus/_query.py +38 -0
  15. modus/_retry.py +123 -0
  16. modus/_streaming.py +115 -0
  17. modus/_validation.py +61 -0
  18. modus/_version.py +24 -0
  19. modus/management/__init__.py +74 -0
  20. modus/management/_client.py +168 -0
  21. modus/management/resources/__init__.py +21 -0
  22. modus/management/resources/_access_config_write.py +31 -0
  23. modus/management/resources/context/__init__.py +0 -0
  24. modus/management/resources/context/_content_merge.py +128 -0
  25. modus/management/resources/context/context.py +362 -0
  26. modus/management/resources/context/custom_items.py +318 -0
  27. modus/management/resources/context/items.py +234 -0
  28. modus/management/resources/organization.py +52 -0
  29. modus/management/resources/scopes/__init__.py +0 -0
  30. modus/management/resources/scopes/_update_body.py +38 -0
  31. modus/management/resources/scopes/conversations.py +177 -0
  32. modus/management/resources/scopes/evaluations.py +142 -0
  33. modus/management/resources/scopes/memories.py +273 -0
  34. modus/management/resources/scopes/scopes.py +764 -0
  35. modus/management/resources/scopes/supervision.py +85 -0
  36. modus/management/resources/usage.py +92 -0
  37. modus/management/resources/users.py +56 -0
  38. modus/management/resources/workflows/__init__.py +0 -0
  39. modus/management/resources/workflows/_update_body.py +29 -0
  40. modus/management/resources/workflows/interfaces.py +136 -0
  41. modus/management/resources/workflows/workflows.py +647 -0
  42. modus/management/types/__init__.py +57 -0
  43. modus/management/types/_guardrails_access.py +33 -0
  44. modus/management/types/_serialize.py +52 -0
  45. modus/management/types/agent_selection.py +66 -0
  46. modus/management/types/agents.py +5 -0
  47. modus/management/types/context.py +25 -0
  48. modus/management/types/conversations.py +5 -0
  49. modus/management/types/evaluations.py +25 -0
  50. modus/management/types/json_blob.py +51 -0
  51. modus/management/types/memories.py +69 -0
  52. modus/management/types/ownership.py +9 -0
  53. modus/management/types/skills.py +5 -0
  54. modus/management/types/toolset.py +236 -0
  55. modus/management/types/triggers.py +284 -0
  56. modus/management/types/usage.py +13 -0
  57. modus/management/types/workflow.py +45 -0
  58. modus/py.typed +0 -0
  59. modus/resources/__init__.py +21 -0
  60. modus/resources/connections/__init__.py +3 -0
  61. modus/resources/connections/connections.py +189 -0
  62. modus/resources/context/__init__.py +3 -0
  63. modus/resources/context/context.py +48 -0
  64. modus/resources/context/items.py +410 -0
  65. modus/resources/modus/__init__.py +3 -0
  66. modus/resources/modus/conversations.py +144 -0
  67. modus/resources/modus/modus.py +138 -0
  68. modus/resources/scopes/__init__.py +3 -0
  69. modus/resources/scopes/conversations.py +213 -0
  70. modus/resources/scopes/scopes.py +431 -0
  71. modus/resources/suggestions/__init__.py +3 -0
  72. modus/resources/suggestions/suggestions.py +207 -0
  73. modus/resources/workflows/__init__.py +15 -0
  74. modus/resources/workflows/runs.py +833 -0
  75. modus/resources/workflows/workflow_actions.py +122 -0
  76. modus/resources/workflows/workflows.py +358 -0
  77. modus/types/__init__.py +80 -0
  78. modus/types/agent_runs.py +70 -0
  79. modus/types/agents.py +17 -0
  80. modus/types/chat.py +9 -0
  81. modus/types/compose.py +21 -0
  82. modus/types/connections.py +9 -0
  83. modus/types/context.py +28 -0
  84. modus/types/context_accessors.py +89 -0
  85. modus/types/context_compose.py +18 -0
  86. modus/types/context_values.py +21 -0
  87. modus/types/conversations.py +30 -0
  88. modus/types/json_blob.py +24 -0
  89. modus/types/pagination.py +142 -0
  90. modus/types/runs.py +71 -0
  91. modus/types/skills.py +16 -0
  92. modus/types/suggestions.py +16 -0
  93. modus/types/tool_calls.py +34 -0
  94. modus/types/views.py +6 -0
  95. modus_sdk-0.2.0.dist-info/METADATA +225 -0
  96. modus_sdk-0.2.0.dist-info/RECORD +98 -0
  97. modus_sdk-0.2.0.dist-info/WHEEL +4 -0
  98. modus_sdk-0.2.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,3182 @@
1
+ # Auto-generated from the Modus API schema. Do not edit by hand.
2
+ from __future__ import annotations
3
+
4
+ from enum import Enum
5
+ from typing import Any
6
+
7
+ from pydantic import AwareDatetime, BaseModel, ConfigDict, Field
8
+ from pydantic.alias_generators import to_camel
9
+
10
+
11
+ class Visibility(str, Enum):
12
+ shared = 'shared'
13
+ private = 'private'
14
+
15
+
16
+ class Scope(str, Enum):
17
+ all = 'all'
18
+ groups = 'groups'
19
+ users = 'users'
20
+
21
+
22
+ class AccessPolicyDto(BaseModel):
23
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
24
+ scope: Scope | None = Field(
25
+ Scope.all, description='Visibility mode. Defaults to org-wide ("all") when omitted.'
26
+ )
27
+ group_ids: list[str] | None = Field(
28
+ None,
29
+ alias='groupIds',
30
+ description='Member group uuids granted access. Required when scope is "groups".',
31
+ )
32
+ user_ids: list[str] | None = Field(
33
+ None,
34
+ alias='userIds',
35
+ description='Clerk user ids granted access. Required when scope is "users".',
36
+ )
37
+
38
+
39
+ class ManageDenial(str, Enum):
40
+ not_owner = 'not_owner'
41
+ needs_group_manage = 'needs_group_manage'
42
+
43
+
44
+ class AgentGroupPermissionDto(BaseModel):
45
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
46
+ use: bool = Field(
47
+ ...,
48
+ description='Whether members of this group may use (run / invoke) the workflow.',
49
+ examples=[True],
50
+ )
51
+ manage: bool = Field(
52
+ ...,
53
+ description='Whether members of this group may manage (edit / deploy / delete) the workflow.',
54
+ examples=[False],
55
+ )
56
+
57
+
58
+ class AgentInterfaceType(str, Enum):
59
+ slack = 'slack'
60
+ mcp = 'mcp'
61
+ teams = 'teams'
62
+
63
+
64
+ class AgentSelectionEntryDto(BaseModel):
65
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
66
+ agent_id: float = Field(
67
+ ...,
68
+ description='Numeric scope (workflow) id to invoke at this step.',
69
+ examples=[17],
70
+ ge=1.0,
71
+ )
72
+ priority_order: float = Field(
73
+ ..., description='Execution order (1-indexed).', examples=[1], ge=1.0
74
+ )
75
+ role: str | None = Field(None, description='Optional role label.', examples=['researcher'])
76
+ instructions: str | None = Field(
77
+ None,
78
+ description='Per-step instructions added to the prompt.',
79
+ examples=['Focus on the last 30 days of data'],
80
+ )
81
+ tool_restrictions: list[str] | None = Field(
82
+ None, description='Optional allowlist of tools the step may call.'
83
+ )
84
+
85
+
86
+ class AgentSharedUserDto(BaseModel):
87
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
88
+ email: str = Field(
89
+ ...,
90
+ description='Lowercased email of a user explicitly granted access to a private workflow.',
91
+ examples=['alice@example.com'],
92
+ )
93
+ added_at: str | None = Field(
94
+ None,
95
+ alias='addedAt',
96
+ description='ISO-8601 timestamp at which this user was added to the share list.',
97
+ examples=['2026-05-01T10:00:00Z'],
98
+ )
99
+ added_by: str | None = Field(
100
+ None,
101
+ alias='addedBy',
102
+ description='Clerk user id of the principal that added this share entry.',
103
+ examples=['user_2abc'],
104
+ )
105
+ user_id: str | None = Field(
106
+ None,
107
+ alias='userId',
108
+ description='Clerk user id of the invited principal (optional — email is the primary key).',
109
+ examples=['user_2xyz'],
110
+ )
111
+
112
+
113
+ class AgentType(str, Enum):
114
+ task = 'task'
115
+ workflow = 'workflow'
116
+
117
+
118
+ class AgentVariationDto(BaseModel):
119
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
120
+ trigger: dict[str, Any] | None = Field(
121
+ None,
122
+ description='`{trigger_type, schedule?}` blob. `trigger_type` is one of `schedule | webhook | api | slack | manual`.',
123
+ )
124
+ workflow_structure: dict[str, Any] | None = Field(
125
+ None,
126
+ alias='workflowStructure',
127
+ description='Workflow graph (`{nodes, edges}`) when `type` is `workflow`. Null when `type` is `task`.',
128
+ )
129
+ agent_selection: dict[str, Any] | None = Field(
130
+ None,
131
+ alias='agentSelection',
132
+ description='Selected scopes + per-step config (`{agents, model?}`) when `type` is `task`. Null when `type` is `workflow`.',
133
+ )
134
+
135
+
136
+ class ApiErrorCode(str, Enum):
137
+ validation = 'VALIDATION'
138
+ bad_request = 'BAD_REQUEST'
139
+ unauthorized = 'UNAUTHORIZED'
140
+ forbidden = 'FORBIDDEN'
141
+ not_found = 'NOT_FOUND'
142
+ conflict = 'CONFLICT'
143
+ rate_limited = 'RATE_LIMITED'
144
+ internal_error = 'INTERNAL_ERROR'
145
+
146
+
147
+ class ApiErrorStatus(str, Enum):
148
+ invalid_argument = 'INVALID_ARGUMENT'
149
+ unauthenticated = 'UNAUTHENTICATED'
150
+ permission_denied = 'PERMISSION_DENIED'
151
+ not_found = 'NOT_FOUND'
152
+ already_exists = 'ALREADY_EXISTS'
153
+ resource_exhausted = 'RESOURCE_EXHAUSTED'
154
+ internal = 'INTERNAL'
155
+
156
+
157
+ class AutomationRunListItemDto(BaseModel):
158
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
159
+ id: str = Field(
160
+ ...,
161
+ description='Composite run identifier (`workflowId:temporalRunId`).',
162
+ examples=['wf_42_run_1:11111111-2222-3333-4444-555555555555'],
163
+ )
164
+ workflow_id: str = Field(
165
+ ..., alias='workflowId', description='Workflow run identifier.', examples=['wf_42_run_1']
166
+ )
167
+ temporal_run_id: str | None = Field(
168
+ None,
169
+ alias='temporalRunId',
170
+ description='Run identifier; a workflow may have multiple runs after a retry.',
171
+ )
172
+ agent_id: float = Field(..., alias='agentId', description='Parent workflow id.', examples=[42])
173
+ agent_name: str = Field(
174
+ ...,
175
+ alias='agentName',
176
+ description='Snapshot of the workflow name at the time the run was indexed.',
177
+ examples=['Daily Sales Report'],
178
+ )
179
+ agent_type: AgentType = Field(
180
+ ..., alias='agentType', description='Workflow type.', examples=['task']
181
+ )
182
+ status: str = Field(
183
+ ...,
184
+ description='Run status (running / awaiting_human / completed / error / cancelled).',
185
+ examples=['completed'],
186
+ )
187
+ trigger_type: str | None = Field(
188
+ None,
189
+ alias='triggerType',
190
+ description='Trigger type for the run (schedule / webhook / api / slack / manual).',
191
+ )
192
+ started_at: str | None = Field(None, alias='startedAt', description='ISO-8601 start timestamp.')
193
+ ended_at: str | None = Field(
194
+ None, alias='endedAt', description='ISO-8601 end timestamp; absent for in-flight runs.'
195
+ )
196
+ duration_ms: float | None = Field(
197
+ None,
198
+ alias='durationMs',
199
+ description='Duration in milliseconds (when end timestamp is known).',
200
+ )
201
+ summary: str | None = Field(
202
+ None, description='Short human-readable summary of the run outcome.'
203
+ )
204
+ pending_approval: dict[str, Any] | None = Field(
205
+ None,
206
+ alias='pendingApproval',
207
+ description='Pending approval payload (only present when status is awaiting_human).',
208
+ )
209
+
210
+
211
+ class AutomationRunSource(str, Enum):
212
+ live_query = 'live-query'
213
+ history = 'history'
214
+
215
+
216
+ class ComposeSkillContextRequestDto(BaseModel):
217
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
218
+ message: str = Field(
219
+ ...,
220
+ description='User message or intent used to compose relevant context (RAG query).',
221
+ examples=['What tables describe customer churn?'],
222
+ min_length=1,
223
+ )
224
+ limit: float | None = Field(
225
+ None,
226
+ description='Optional cap on context items when the API falls back to structured JSON (no fragment markdown). Ignored when composed markdown is returned.',
227
+ examples=[25],
228
+ ge=1.0,
229
+ le=200.0,
230
+ )
231
+
232
+
233
+ class ComposeSkillContextResponseDto(BaseModel):
234
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
235
+ context: str = Field(..., description='Composed context for the scope and intent (markdown from the context composer, or structured JSON fallback).', examples=['## Retrieved Context\n\n### customers\n\n...'])
236
+ context_items: list[dict[str, Any]] = Field(
237
+ ...,
238
+ alias='contextItems',
239
+ deprecated=True,
240
+ description='Deprecated. Always an empty array. Use `context` for composed text (markdown or JSON fallback).',
241
+ examples=[[]],
242
+ )
243
+ original_count: float = Field(
244
+ ...,
245
+ alias='originalCount',
246
+ description="Total context items in the scope's configured context selection (before composition strategies).",
247
+ examples=[42],
248
+ )
249
+ selected_count: float = Field(
250
+ ...,
251
+ alias='selectedCount',
252
+ description='Context items the composer kept for this intent.',
253
+ examples=[12],
254
+ )
255
+ session_id: str = Field(
256
+ ...,
257
+ alias='sessionId',
258
+ description='Session id used for this composition (for correlation).',
259
+ examples=['api-skill-42-550e8400-e29b-41d4-a716-446655440000'],
260
+ )
261
+
262
+
263
+ class ConnectionDto(BaseModel):
264
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
265
+ id: str = Field(
266
+ ...,
267
+ description='Integration connection UUID.',
268
+ examples=['7a3f9d2c-1111-4000-a000-000000000abc'],
269
+ )
270
+ name: str | None = Field(
271
+ ...,
272
+ description='Human-readable connection name configured in the org.',
273
+ examples=['Production Warehouse'],
274
+ )
275
+ type: str | None = Field(
276
+ ...,
277
+ description='Effective integration category for the connection (e.g. postgresql, bigquery).',
278
+ examples=['postgresql'],
279
+ )
280
+
281
+
282
+ class ContentProjectionDto(BaseModel):
283
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
284
+ fields: list[str] | None = Field(
285
+ None, description='Top-level scalar field names to project.', examples=[['isPartial']]
286
+ )
287
+ arrays: dict[str, list[str]] | None = Field(
288
+ None,
289
+ description='Per-array projection: object keys are array field names; the value lists the element fields to keep.',
290
+ examples=[{'channels': ['channelId', 'channelName', 'isPrivate']}],
291
+ )
292
+
293
+
294
+ class UserFeedback(str, Enum):
295
+ negative = 'negative'
296
+ neutral = 'neutral'
297
+ positive = 'positive'
298
+
299
+
300
+ class ContextItemDto(BaseModel):
301
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
302
+ uid: str = Field(
303
+ ...,
304
+ description='Stable UUID for the context item. Use this on PATCH / DELETE / values endpoints.',
305
+ examples=['7a3f9d2c-1111-4000-a000-000000000abc'],
306
+ )
307
+ org_id: str = Field(
308
+ ...,
309
+ alias='orgId',
310
+ description='Org UUID this item belongs to. Matches the caller’s principal.',
311
+ examples=['00000000-0000-0000-0000-000000000001'],
312
+ )
313
+ context_type: str = Field(
314
+ ...,
315
+ alias='contextType',
316
+ description='Per-row context type identifier — one of `note`, `link`, `saved_query`, plus the dozens of integration-driven types (e.g. `looker_dashboard_metadata`, `salesforce_object_field`).',
317
+ examples=['note'],
318
+ )
319
+ content: dict[str, Any] = Field(
320
+ ...,
321
+ description='Type-specific JSON content. Shape varies by `contextType`; treat as opaque unless you know the kind.',
322
+ )
323
+ description: str | None = Field(
324
+ None,
325
+ description='Human-readable description (separate from the type-specific `content` blob).',
326
+ examples=['Q3 churn analysis notes'],
327
+ )
328
+ user_feedback: UserFeedback = Field(
329
+ ...,
330
+ alias='userFeedback',
331
+ description='User-supplied verification verdict. `positive` ≈ approved/verified; `negative` ≈ rejected/dismissed; `neutral` is the default.',
332
+ examples=['neutral'],
333
+ )
334
+ topics: list[str] = Field(
335
+ ...,
336
+ description='Free-form topic tags. Used for sidebar filtering on the SPA.',
337
+ examples=[['analytics', 'q3']],
338
+ )
339
+ connection_id: str | None = Field(
340
+ None,
341
+ alias='connectionId',
342
+ description='Originating integration connection id for integration-derived items. Null for user-created items.',
343
+ examples=['00000000-0000-4000-a000-000000000111'],
344
+ )
345
+ selection_id: str | None = Field(
346
+ None,
347
+ alias='selectionId',
348
+ description='Originating selection id (datamap-scoped) for integration-derived items.',
349
+ examples=['00000000-0000-4000-a000-000000000222'],
350
+ )
351
+ data_path: list[str] = Field(
352
+ ...,
353
+ alias='dataPath',
354
+ description='Hierarchical path that places the item inside the data map (used for filtering by data asset).',
355
+ examples=[['salesforce', '00000000-0000-4000-a000-000000000111', 'Account', 'Name']],
356
+ )
357
+ created_at: str = Field(
358
+ ...,
359
+ alias='createdAt',
360
+ description='Creation timestamp.',
361
+ examples=['2026-05-01T10:00:00.000Z'],
362
+ )
363
+ updated_at: str = Field(
364
+ ...,
365
+ alias='updatedAt',
366
+ description='Most recent update timestamp.',
367
+ examples=['2026-05-11T10:00:00.000Z'],
368
+ )
369
+ last_update_metadata: dict[str, Any] | None = Field(
370
+ None,
371
+ alias='lastUpdateMetadata',
372
+ description='Audit blob recording who/what last edited the item (`action`, `user_id`/`editedByName`/`editedByEmail`, `timestamp`). Used by the SPA to render the "Last Update" column.',
373
+ examples=[{'action': 'auto_analysis', 'timestamp': '2026-05-11T10:00:00.000Z'}],
374
+ )
375
+
376
+
377
+ class ContextItemKind(str, Enum):
378
+ note = 'note'
379
+ saved_query = 'saved_query'
380
+ link = 'link'
381
+
382
+
383
+ class ConversationListItemDto(BaseModel):
384
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
385
+ thread_id: str = Field(
386
+ ..., alias='threadId', description='Opaque thread id.', examples=['agent_42_abc-xyz']
387
+ )
388
+ skill_id: float | None = Field(
389
+ ...,
390
+ alias='skillId',
391
+ description='Numeric scope id returned by the list adapter. This is not conversation ownership.',
392
+ examples=[42],
393
+ )
394
+ first_message: str = Field(
395
+ ...,
396
+ alias='firstMessage',
397
+ description='Preview of the first user turn, used as a list-row caption. Falls back to a stable placeholder when the thread has no human turn yet.',
398
+ examples=['Run the churn analysis for last 30 days.'],
399
+ )
400
+ title: str | None = Field(
401
+ ...,
402
+ description='User-managed display title. Null until the user renames the conversation.',
403
+ examples=['Q3 Revenue Analysis'],
404
+ )
405
+ message_count: float = Field(
406
+ ...,
407
+ alias='messageCount',
408
+ description='Total number of message turns in the (post-collapse) conversation.',
409
+ examples=[12],
410
+ )
411
+ created_at: str = Field(
412
+ ...,
413
+ alias='createdAt',
414
+ description='ISO-8601 timestamp of the first checkpoint.',
415
+ examples=['2026-05-01T10:00:00.000Z'],
416
+ )
417
+ updated_at: str = Field(
418
+ ...,
419
+ alias='updatedAt',
420
+ description='ISO-8601 timestamp of the latest checkpoint.',
421
+ examples=['2026-05-01T11:00:00.000Z'],
422
+ )
423
+ tools_used: list[str] | None = Field(
424
+ None,
425
+ alias='toolsUsed',
426
+ description='Distinct tool names invoked across this conversation. Present only when `includeTools=true` is requested.',
427
+ examples=[['sql_runner']],
428
+ )
429
+ user_ids: list[str] = Field(
430
+ ...,
431
+ alias='userIds',
432
+ description='Distinct user ids that participated in this thread.',
433
+ examples=[['user_abc']],
434
+ )
435
+
436
+
437
+ class ConversationMessageType(str, Enum):
438
+ human = 'human'
439
+ ai = 'ai'
440
+ system = 'system'
441
+ tool = 'tool'
442
+ unknown = 'unknown'
443
+
444
+
445
+ class ConversationMessageWindowDto(BaseModel):
446
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
447
+ start_index: float = Field(
448
+ ...,
449
+ alias='startIndex',
450
+ description='Zero-based source-message index of the first returned message. Source-message indexes include non-visible tool and system messages.',
451
+ examples=[90],
452
+ )
453
+ end_index: float = Field(
454
+ ...,
455
+ alias='endIndex',
456
+ description='Exclusive zero-based source-message index after the last returned message.',
457
+ examples=[120],
458
+ )
459
+ total_messages: float = Field(
460
+ ...,
461
+ alias='totalMessages',
462
+ description='Total source-message count used for paging. The returned visible message array can be shorter than endIndex - startIndex.',
463
+ examples=[120],
464
+ )
465
+ has_more_before: bool = Field(
466
+ ...,
467
+ alias='hasMoreBefore',
468
+ description='Whether an older message window exists before startIndex.',
469
+ examples=[True],
470
+ )
471
+ has_more_after: bool = Field(
472
+ ...,
473
+ alias='hasMoreAfter',
474
+ description='Whether a newer message window exists after endIndex.',
475
+ examples=[False],
476
+ )
477
+
478
+
479
+ class CreateLinkDto(BaseModel):
480
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
481
+ url: str = Field(
482
+ ...,
483
+ description='URL to extract content from. Invoked via Tavily.',
484
+ examples=['https://example.com/blog/post'],
485
+ )
486
+ title: str | None = Field(
487
+ None,
488
+ description='Optional title override. When omitted, Tavily-derived metadata or the URL hostname is used.',
489
+ examples=['Example blog post'],
490
+ )
491
+ is_crawl: bool | None = Field(
492
+ False,
493
+ alias='isCrawl',
494
+ description='When true, crawls multiple pages starting from the supplied URL.',
495
+ examples=[False],
496
+ )
497
+ page_limit: float | None = Field(
498
+ None,
499
+ alias='pageLimit',
500
+ description='Maximum number of pages to crawl when `isCrawl` is true. Ignored otherwise.',
501
+ examples=[10],
502
+ ge=1.0,
503
+ le=200.0,
504
+ )
505
+ access: AccessPolicyDto | None = None
506
+
507
+
508
+ class CreateNoteDto(BaseModel):
509
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
510
+ title: str | None = Field(
511
+ ...,
512
+ description='Display title for the note. Used in the SPA list and as the s3 object filename.',
513
+ examples=['Q3 churn analysis'],
514
+ )
515
+ content: str = Field(..., description='Note body — markdown text. Stored in tenant S3 + context_items.', examples=['## Findings\n\nChurn rate increased 2.3% MoM.'])
516
+ access: AccessPolicyDto | None = None
517
+
518
+
519
+ class CreateSavedQueryDto(BaseModel):
520
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
521
+ name: str | None = Field(
522
+ ..., description='Display name for the saved query.', examples=['Top customers Q3']
523
+ )
524
+ query: str | None = Field(
525
+ None,
526
+ description='SQL text. Stored in tenant S3 + context_items. May be omitted or empty when creating a placeholder saved query.',
527
+ examples=['SELECT customer_id, SUM(amount) FROM orders GROUP BY 1 ORDER BY 2 DESC LIMIT 10'],
528
+ )
529
+ connection_id: str | None = Field(
530
+ ...,
531
+ alias='connectionId',
532
+ description='Data connection id this query targets. Must reference an existing integration connection in the org.',
533
+ examples=['00000000-0000-4000-a000-000000000111'],
534
+ )
535
+ description: str | None = Field(
536
+ None,
537
+ description='Optional one-line description shown in the SPA list.',
538
+ examples=['Quarterly cohort by amount.'],
539
+ )
540
+ path: list[str] | None = Field(
541
+ None,
542
+ description='Optional hierarchical path identifying the data scope (e.g. `["database", "schema"]` for Snowflake; `["dataset"]` for BigQuery).',
543
+ examples=[['my_dataset']],
544
+ )
545
+ access: AccessPolicyDto | None = None
546
+
547
+
548
+ class CreatedContextItemResponseDto(BaseModel):
549
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
550
+ context_item_id: str = Field(
551
+ ...,
552
+ alias='contextItemId',
553
+ description='UUID of the newly-created context item. Use it on subsequent GET / PATCH / DELETE calls.',
554
+ examples=['7a3f9d2c-1111-4000-a000-000000000abc'],
555
+ )
556
+ kind: ContextItemKind = Field(
557
+ ..., description='Kind of context item created.', examples=['note']
558
+ )
559
+ s3_key: str | None = Field(
560
+ None,
561
+ alias='s3Key',
562
+ description='Tenant S3 key for the raw content blob (notes, saved queries, links). Null for kinds without S3 backing.',
563
+ examples=['context_notes/7a3f9d2c.../Q3_churn_analysis.md'],
564
+ )
565
+ title: str | None = Field(
566
+ None,
567
+ description='Resolved title for the created item. Null for kinds without a title field.',
568
+ examples=['Q3 churn analysis'],
569
+ )
570
+
571
+
572
+ class CreatedCustomContextItemResponseDto(BaseModel):
573
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
574
+ context_item_id: str = Field(
575
+ ...,
576
+ alias='contextItemId',
577
+ description='Stable uid of the created or updated custom context item.',
578
+ examples=['7a3f9d2c-1111-4000-a000-000000000abc'],
579
+ )
580
+ context_type: str = Field(
581
+ ...,
582
+ alias='contextType',
583
+ description='Stored custom context type.',
584
+ examples=['custom_entity_metadata'],
585
+ )
586
+ data_path: list[str] = Field(
587
+ ...,
588
+ alias='dataPath',
589
+ description='Hierarchical path used to group custom context.',
590
+ examples=[['billing-db', 'contracts', 'contract-123']],
591
+ )
592
+ title: str | None = Field(
593
+ ..., description='Display title resolved for the item.', examples=['Acme renewal contract']
594
+ )
595
+
596
+
597
+ class CustomAttributeDto(BaseModel):
598
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
599
+ name: str | None = Field(..., description='Attribute name.', examples=['status'])
600
+ data_type: str | None = Field(
601
+ None, alias='dataType', description='Customer-defined attribute type.', examples=['string']
602
+ )
603
+ value: dict[str, Any] | None = Field(
604
+ None, description='Representative value for this attribute.'
605
+ )
606
+
607
+
608
+ class CustomContextItemKind(str, Enum):
609
+ source = 'source'
610
+ collection = 'collection'
611
+ entity = 'entity'
612
+ field = 'field'
613
+ entity_samples = 'entity_samples'
614
+
615
+
616
+ class DeleteContextItemResponseDto(BaseModel):
617
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
618
+ uid: str = Field(
619
+ ...,
620
+ description='UUID of the deleted context item.',
621
+ examples=['7a3f9d2c-1111-4000-a000-000000000abc'],
622
+ )
623
+ context_type: str = Field(
624
+ ...,
625
+ alias='contextType',
626
+ description='Resolved context type at delete time. Always one of `note`, `link`, `saved_query`, `golden_query`, `file_upload`.',
627
+ examples=['note'],
628
+ )
629
+
630
+
631
+ class DeployAgentDto(BaseModel):
632
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
633
+ expected_main_sha_override: (
634
+ str | None
635
+ ) = (
636
+ Field(None, alias='expectedMainShaOverride', description='SHA the SPA last saw the remote file at; lets the user force-push past a previous drift by acknowledging the version they are overwriting. Empty string is treated as absent.', examples=['a1b2c3d4e5f607890123456789abcdef01234567'], max_length=200)
637
+ )
638
+
639
+
640
+ class DeploySkillDto(BaseModel):
641
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
642
+ expected_main_sha_override: (
643
+ str | None
644
+ ) = (
645
+ Field(None, alias='expectedMainShaOverride', description='SHA the SPA last saw the remote file at; lets the user force-push past a previous drift by acknowledging the version they are overwriting. Empty string is treated as absent.', examples=['a1b2c3d4e5f607890123456789abcdef01234567'], max_length=200)
646
+ )
647
+
648
+
649
+ class ErrorEnvelopeDto(BaseModel):
650
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
651
+ code: ApiErrorCode = Field(..., description='Modus-specific machine code.')
652
+ status: ApiErrorStatus = Field(..., description='Canonical status string for the error.')
653
+ message: str = Field(..., examples=['Skill was not found or you lack permission.'])
654
+ request_id: str = Field(..., alias='requestId', examples=['req_01HQ7K8ABCDEFGHIJKLMNOPQRS'])
655
+ info: dict[str, Any] | None = Field(
656
+ None,
657
+ description="Optional domain-specific context. Shape varies per endpoint — see the operation's error response examples.",
658
+ examples=[{'skillId': 'sk_abc123'}],
659
+ )
660
+
661
+
662
+ class ErrorResponseDto(BaseModel):
663
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
664
+ error: ErrorEnvelopeDto
665
+
666
+
667
+ class EvaluationCadenceFrequency(str, Enum):
668
+ daily = 'daily'
669
+ weekly = 'weekly'
670
+ monthly = 'monthly'
671
+ custom = 'custom'
672
+
673
+
674
+ class EvaluationRecipientDto(BaseModel):
675
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
676
+ clerk_user_id: str = Field(..., alias='clerkUserId', description='Clerk user ID')
677
+ email: str = Field(..., description='Email address')
678
+ name: dict[str, Any] | None = Field(None, description='Display name')
679
+
680
+
681
+ class EvaluationResultDto(BaseModel):
682
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
683
+ id: str = Field(..., description='Result ID')
684
+ case_id: str = Field(..., alias='caseId', description='Evaluation case ID')
685
+ task: str = Field(..., description='Task that was evaluated')
686
+ expected_output: str = Field(..., alias='expectedOutput', description='Expected output')
687
+ actual_output: dict[str, Any] | None = Field(
688
+ None, alias='actualOutput', description='Actual output from the scope'
689
+ )
690
+ passed: dict[str, Any] | None = Field(None, description='Whether the case passed')
691
+ score: dict[str, Any] | None = Field(None, description='Score (0-100)')
692
+ reasoning: dict[str, Any] | None = Field(None, description='Judge reasoning')
693
+ was_passing_before: dict[str, Any] | None = Field(
694
+ None,
695
+ alias='wasPassingBefore',
696
+ description='Whether this case was passing in the previous run',
697
+ )
698
+
699
+
700
+ class EvaluationRunStatus(str, Enum):
701
+ running = 'running'
702
+ completed = 'completed'
703
+ completed_with_errors = 'completed_with_errors'
704
+ failed = 'failed'
705
+
706
+
707
+ class EvaluationRunTrigger(str, Enum):
708
+ scheduled = 'scheduled'
709
+ manual = 'manual'
710
+
711
+
712
+ class EvaluationRunWithResultsDto(BaseModel):
713
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
714
+ id: str = Field(..., description='Run ID')
715
+ skill_id: float | None = Field(..., alias='skillId', description='Scope ID')
716
+ trigger: EvaluationRunTrigger | None = Field(..., description='How the run was triggered')
717
+ status: EvaluationRunStatus = Field(..., description='Run status')
718
+ started_at: str = Field(..., alias='startedAt', description='When the run started')
719
+ finished_at: dict[str, Any] | None = Field(
720
+ None, alias='finishedAt', description='When the run finished'
721
+ )
722
+ total_cases: float = Field(
723
+ ..., alias='totalCases', description='Total number of evaluation cases'
724
+ )
725
+ passed_cases: float = Field(..., alias='passedCases', description='Number of passed cases')
726
+ failed_cases: float = Field(..., alias='failedCases', description='Number of failed cases')
727
+ avg_score: dict[str, Any] | None = Field(
728
+ None, alias='avgScore', description='Average score (0-100)'
729
+ )
730
+ is_regression: bool = Field(
731
+ ..., alias='isRegression', description='Whether this run detected a regression'
732
+ )
733
+ judge_model: str | None = Field(None, alias='judgeModel', description='Judge model used')
734
+ error_message: str | None = Field(
735
+ None, alias='errorMessage', description='Error message if failed'
736
+ )
737
+ results: list[EvaluationResultDto] = Field(..., description='Per-case results')
738
+
739
+
740
+ class EvaluationSlackChannelDto(BaseModel):
741
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
742
+ nango_connection_id: str = Field(
743
+ ..., alias='nangoConnectionId', description='Nango connection ID for Slack'
744
+ )
745
+ slack_user_id_by_recipient: dict[str, Any] = Field(
746
+ ..., alias='slackUserIdByRecipient', description='Mapping of Clerk user ID to Slack user ID'
747
+ )
748
+
749
+
750
+ class StatusReason(str, Enum):
751
+ approval_timeout = 'approval_timeout'
752
+
753
+
754
+ class GetAutomationRunResponseDto(BaseModel):
755
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
756
+ id: str = Field(
757
+ ...,
758
+ description='Composite run identifier (`workflowId:temporalRunId`).',
759
+ examples=['wf_42_run_1:11111111-2222-3333-4444-555555555555'],
760
+ )
761
+ workflow_id: str = Field(
762
+ ..., alias='workflowId', description='Workflow run identifier.', examples=['wf_42_run_1']
763
+ )
764
+ temporal_run_id: str | None = Field(
765
+ None,
766
+ alias='temporalRunId',
767
+ description='Run identifier; a workflow may have multiple runs after a retry.',
768
+ )
769
+ agent_id: float = Field(..., alias='agentId', description='Parent workflow id.', examples=[42])
770
+ agent_name: str = Field(
771
+ ...,
772
+ alias='agentName',
773
+ description='Snapshot of the workflow name at the time the run was indexed.',
774
+ examples=['Daily Sales Report'],
775
+ )
776
+ agent_type: AgentType = Field(
777
+ ..., alias='agentType', description='Workflow type.', examples=['task']
778
+ )
779
+ status: str = Field(
780
+ ...,
781
+ description='Run status (running / awaiting_human / completed / error / cancelled).',
782
+ examples=['completed'],
783
+ )
784
+ trigger_type: str | None = Field(
785
+ None,
786
+ alias='triggerType',
787
+ description='Trigger type for the run (schedule / webhook / api / slack / manual).',
788
+ )
789
+ started_at: str | None = Field(None, alias='startedAt', description='ISO-8601 start timestamp.')
790
+ ended_at: str | None = Field(
791
+ None, alias='endedAt', description='ISO-8601 end timestamp; absent for in-flight runs.'
792
+ )
793
+ duration_ms: float | None = Field(
794
+ None,
795
+ alias='durationMs',
796
+ description='Duration in milliseconds (when end timestamp is known).',
797
+ )
798
+ summary: str | None = Field(
799
+ None, description='Short human-readable summary of the run outcome.'
800
+ )
801
+ pending_approval: dict[str, Any] | None = Field(
802
+ None,
803
+ alias='pendingApproval',
804
+ description='Pending approval payload (only present when status is awaiting_human).',
805
+ )
806
+ status_reason: StatusReason | None = Field(
807
+ None,
808
+ alias='statusReason',
809
+ description='Display-only signal that the workflow closed for a non-success reason.',
810
+ )
811
+ source: AutomationRunSource = Field(
812
+ ...,
813
+ description='Where the payload was read from. `live-query` = the run is still in progress; `history` = a completed run.',
814
+ )
815
+ task_result: dict[str, Any] | None = Field(
816
+ None,
817
+ alias='taskResult',
818
+ description='Final result of a `task`-typed workflow run. Free-form (depends on the workflow).',
819
+ )
820
+ task_error: str | None = Field(
821
+ None, alias='taskError', description='Error message for a failed `task`-typed workflow run.'
822
+ )
823
+ workflow_nodes: list[dict[str, Any]] | None = Field(
824
+ None,
825
+ alias='workflowNodes',
826
+ description='Per-node state for a `workflow`-typed workflow run.',
827
+ )
828
+ history_unavailable_reason: (
829
+ str | None
830
+ ) = (
831
+ Field(None, alias='historyUnavailableReason', description='Set when history was unavailable; `source` will be `live-query` in that case.')
832
+ )
833
+
834
+
835
+ class GroupPermissionDto(BaseModel):
836
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
837
+ use: bool = Field(
838
+ ...,
839
+ description='Whether members of this group may use (run / invoke) the scope.',
840
+ examples=[True],
841
+ )
842
+ manage: bool = Field(
843
+ ...,
844
+ description='Whether members of this group may manage (edit / deploy / delete) the scope.',
845
+ examples=[False],
846
+ )
847
+
848
+
849
+ class ListAutomationRunsResponseDto(BaseModel):
850
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
851
+ runs: list[AutomationRunListItemDto] = Field(
852
+ ..., description='Page of run summaries, most recent first.'
853
+ )
854
+ next_page_token: str | None = Field(
855
+ None,
856
+ alias='nextPageToken',
857
+ description='Opaque token for the next page; null when this was the last page. Pass as `pageToken` on the next request.',
858
+ )
859
+ counts: dict[str, float] = Field(
860
+ ...,
861
+ description='Per-status counts (all_executions / running / awaiting_human / error / completed).',
862
+ examples=[{'all_executions': 100, 'running': 1, 'awaiting_human': 0, 'error': 2, 'completed': 97}],
863
+ )
864
+
865
+
866
+ class ListConnectionsResponseDto(BaseModel):
867
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
868
+ connections: list[ConnectionDto] = Field(
869
+ ...,
870
+ description='Page of integration connections the caller can `use`. Connections the caller cannot access are filtered out (not enumerated).',
871
+ )
872
+ next_page_token: str | None = Field(
873
+ ...,
874
+ alias='nextPageToken',
875
+ description='Opaque token for the next page; `null` when this was the last page. Pass as `pageToken` on the next request.',
876
+ examples=['eyJjcmVhdGVkQXQiOiIyMDI2'],
877
+ )
878
+
879
+
880
+ class ListContextItemValuesResponseDto(BaseModel):
881
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
882
+ values: list[Any] = Field(
883
+ ...,
884
+ description='Page of values extracted from the context item at the supplied `contentKeyPath`. Each entry is opaque JSON whose shape depends on the source item.',
885
+ )
886
+ next_page_token: str | None = Field(
887
+ ...,
888
+ alias='nextPageToken',
889
+ description='Opaque token for the next page, or `null` if no more pages. Pass back as `pageToken`.',
890
+ )
891
+
892
+
893
+ class ListContextItemsResponseDto(BaseModel):
894
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
895
+ context_items: list[ContextItemDto] = Field(
896
+ ...,
897
+ alias='contextItems',
898
+ description='Page of context items. Empty when no items match the filter.',
899
+ )
900
+ next_page_token: str | None = Field(
901
+ ...,
902
+ alias='nextPageToken',
903
+ description='Opaque token for the next page; `null` when this was the last page. Pass as `pageToken` on the next request. Required-but-nullable — the field is always present on every response.',
904
+ examples=['eyJjcmVhdGVkQXQiOiIyMDI2LTA1LTAxIiwidWlkIjoiYWJjIn0'],
905
+ )
906
+ total_count: float | None = Field(
907
+ None,
908
+ alias='totalCount',
909
+ description='Approximate total count of matching items (when known). Some filter combinations skip this for cost reasons.',
910
+ examples=[142],
911
+ )
912
+
913
+
914
+ class ListConversationsResponseDto(BaseModel):
915
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
916
+ conversations: list[ConversationListItemDto] = Field(
917
+ ..., description='Page of conversation summaries, newest-updated first.'
918
+ )
919
+ next_page_token: str | None = Field(
920
+ ...,
921
+ alias='nextPageToken',
922
+ description='Opaque token for the next page. `null` when there are no further pages.',
923
+ examples=['eyJwYWdlIjoxLCJwYWdlU2l6ZSI6MTB9'],
924
+ )
925
+ total_count: float | None = Field(
926
+ ...,
927
+ alias='totalCount',
928
+ description='Total threads visible in the scanned window after filters. Not a global count.',
929
+ examples=[47],
930
+ )
931
+ page: float | None = Field(
932
+ None,
933
+ description='Legacy echo of the requested 0-indexed page. Retained for SPA backwards-compatibility; new callers should rely on `pageToken` / `nextPageToken`.',
934
+ examples=[0],
935
+ )
936
+ page_size: float | None = Field(
937
+ None,
938
+ alias='pageSize',
939
+ description='Legacy echo of the requested `pageSize`. Retained for SPA backwards-compatibility.',
940
+ examples=[10],
941
+ )
942
+
943
+
944
+ class ListCustomContextItemsResponseDto(BaseModel):
945
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
946
+ context_items: list[ContextItemDto] = Field(
947
+ ..., alias='contextItems', description='Page of custom context items.'
948
+ )
949
+ next_page_token: str | None = Field(
950
+ ...,
951
+ alias='nextPageToken',
952
+ description='Opaque token for the next page; `null` when this was the last page.',
953
+ )
954
+ total_count: float | None = Field(
955
+ ...,
956
+ alias='totalCount',
957
+ description='Approximate total count of matching custom context items, when known.',
958
+ )
959
+
960
+
961
+ class Rollup(str, Enum):
962
+ hour = 'hour'
963
+ day = 'day'
964
+
965
+
966
+ class GroupBy(str, Enum):
967
+ all = 'all'
968
+ skill = 'skill'
969
+ agent = 'agent'
970
+ interface = 'interface'
971
+ model = 'model'
972
+ attribution = 'attribution'
973
+
974
+
975
+ class LookupContextItemDto(BaseModel):
976
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
977
+ context_type: str = Field(
978
+ ...,
979
+ alias='contextType',
980
+ description='Context type of the row to fetch (e.g. `slack_channel_metadata`).',
981
+ examples=['slack_channel_metadata'],
982
+ )
983
+ data_path: list[str] = Field(
984
+ ...,
985
+ alias='dataPath',
986
+ description="Hierarchical data path identifying the row. Full equality match against the row's `data_path` column.",
987
+ examples=[['00000000-0000-4000-a000-000000000111', 'T0123456']],
988
+ )
989
+ content_projection: ContentProjectionDto | None = Field(
990
+ None,
991
+ alias='contentProjection',
992
+ description='Optional JSONB projection applied at SQL time to shrink the payload. When omitted the full `content` column is returned.',
993
+ )
994
+
995
+
996
+ class LookupContextItemRowDto(BaseModel):
997
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
998
+ uid: str = Field(..., description='Stable UUID of the context item.')
999
+ context_type: str = Field(
1000
+ ..., alias='contextType', description='Context type (same as the request).'
1001
+ )
1002
+ data_path: list[str] = Field(
1003
+ ...,
1004
+ alias='dataPath',
1005
+ description='Hierarchical data path of the row (same as the request).',
1006
+ )
1007
+ content: dict[str, Any] = Field(
1008
+ ...,
1009
+ description='Item content. When the request supplied a `contentProjection` the JSONB is shaped accordingly; otherwise the full content blob is returned.',
1010
+ )
1011
+ connection_id: str | None = Field(
1012
+ ...,
1013
+ alias='connectionId',
1014
+ description='Origin connection id if the row was emitted by an integration, otherwise null.',
1015
+ )
1016
+ selection_id: str | None = Field(
1017
+ ...,
1018
+ alias='selectionId',
1019
+ description='Selection (per-connection subset) id when the row scopes to a selection, otherwise null.',
1020
+ )
1021
+
1022
+
1023
+ class MemberGroupDto(BaseModel):
1024
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1025
+ uid: str
1026
+ name: str
1027
+ description: str
1028
+ member_ids: list[str]
1029
+ created_at: str
1030
+ updated_at: str
1031
+
1032
+
1033
+ class MemoryDto(BaseModel):
1034
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1035
+ id: str = Field(..., description='Opaque memory id.', examples=['mem_01HRQX...ABC'])
1036
+ memory: str = Field(
1037
+ ...,
1038
+ description='The memory text.',
1039
+ examples=['User prefers concise summaries with bullet points.'],
1040
+ )
1041
+ hash: str | None = Field(None, description='Content hash, useful for de-duplication.')
1042
+ metadata: dict[str, Any] | None = Field(
1043
+ None,
1044
+ description='Opaque metadata bag — caller-supplied tags stored with the memory.',
1045
+ examples=[{'source': 'agent_run_42', 'topic': 'preferences'}],
1046
+ )
1047
+ created_at: str | None = Field(
1048
+ None,
1049
+ alias='createdAt',
1050
+ description='ISO-8601 creation timestamp.',
1051
+ examples=['2026-05-01T10:00:00.000Z'],
1052
+ )
1053
+ updated_at: str | None = Field(
1054
+ None,
1055
+ alias='updatedAt',
1056
+ description='ISO-8601 last-update timestamp.',
1057
+ examples=['2026-05-01T10:00:00.000Z'],
1058
+ )
1059
+
1060
+
1061
+ class Model(str, Enum):
1062
+ claude_sonnet_5 = 'claude-sonnet-5'
1063
+ claude_sonnet_4_6 = 'claude-sonnet-4.6'
1064
+ claude_opus_4_8 = 'claude-opus-4.8'
1065
+ gpt_5_2 = 'gpt-5.2'
1066
+ gpt_5_5 = 'gpt-5.5'
1067
+ gpt_5_mini = 'gpt-5-mini'
1068
+ gpt_oss_120b = 'gpt-oss-120b'
1069
+ gpt_oss_20b = 'gpt-oss-20b'
1070
+ qwen3_235b_a22b_2507 = 'qwen3-235b-a22b-2507'
1071
+ qwen3_coder = 'qwen3-coder'
1072
+ qwen3_32b = 'qwen3-32b'
1073
+ deepseek_chat_v3_1 = 'deepseek-chat-v3.1'
1074
+ minimax_m2_7 = 'minimax-m2.7'
1075
+ llama_4_maverick = 'llama-4-maverick'
1076
+ llama_4_scout = 'llama-4-scout'
1077
+ llama_3_3_70b_instruct = 'llama-3.3-70b-instruct'
1078
+ gemini_3_1_pro_preview = 'gemini-3.1-pro-preview'
1079
+ gemini_3_flash_preview = 'gemini-3-flash-preview'
1080
+ grok_4_3_fast = 'grok-4.3-fast'
1081
+ grok_4_3 = 'grok-4.3'
1082
+
1083
+
1084
+ class ApprovalDecision(str, Enum):
1085
+ approve = 'approve'
1086
+ deny = 'deny'
1087
+
1088
+
1089
+ class ModusChatRequestDto(BaseModel):
1090
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1091
+ message: str | None = Field(
1092
+ None,
1093
+ description='User message sent to Modus. Omit when `approvalContinuation` is true.',
1094
+ examples=['What were our top revenue drivers last quarter?'],
1095
+ min_length=1,
1096
+ )
1097
+ model: Model | None = Field(
1098
+ ...,
1099
+ description='Canonical model id for this run (required). Allowed values: claude-sonnet-5, claude-sonnet-4.6, claude-opus-4.8, gpt-5.2, gpt-5.5, gpt-5-mini, gpt-oss-120b, gpt-oss-20b, qwen3-235b-a22b-2507, qwen3-coder, qwen3-32b, deepseek-chat-v3.1, minimax-m2.7, llama-4-maverick, llama-4-scout, llama-3.3-70b-instruct, gemini-3.1-pro-preview, gemini-3-flash-preview, grok-4.3-fast, grok-4.3.',
1100
+ examples=['claude-sonnet-4.6'],
1101
+ )
1102
+ approval_continuation: bool | None = Field(
1103
+ None,
1104
+ alias='approvalContinuation',
1105
+ description='Continue a pending write-approval interrupt from a prior turn. When true, `message` is ignored.',
1106
+ )
1107
+ approval_decision: ApprovalDecision | None = Field(
1108
+ None, alias='approvalDecision', description='Required when `approvalContinuation` is true.'
1109
+ )
1110
+
1111
+
1112
+ class ModusChatResponseDto(BaseModel):
1113
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1114
+ content: str = Field(
1115
+ ...,
1116
+ description='Final assistant text for the run.',
1117
+ examples=['Revenue grew 12% quarter over quarter…'],
1118
+ )
1119
+ thread_id: str = Field(
1120
+ ...,
1121
+ alias='threadId',
1122
+ description='Conversation thread id. For follow-up use POST …/conversations/{threadId}/chat.',
1123
+ examples=['agent_0_550e8400-e29b-41d4-a716-446655440000'],
1124
+ )
1125
+ run_id: str = Field(
1126
+ ...,
1127
+ alias='runId',
1128
+ description='Opaque run id for this chat invocation.',
1129
+ examples=['550e8400-e29b-41d4-a716-446655440001'],
1130
+ )
1131
+
1132
+
1133
+ class ModusContextRequestDto(BaseModel):
1134
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1135
+ message: str = Field(
1136
+ ...,
1137
+ description='User message or intent used to compose relevant context.',
1138
+ examples=['What tables describe customer churn?'],
1139
+ min_length=1,
1140
+ )
1141
+ limit: float | None = Field(
1142
+ None,
1143
+ description='Optional cap on context items in structured JSON fallback.',
1144
+ examples=[25],
1145
+ ge=1.0,
1146
+ le=200.0,
1147
+ )
1148
+
1149
+
1150
+ class ModusContextResponseDto(BaseModel):
1151
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1152
+ context: str = Field(
1153
+ ..., description='Composed context for the intent (markdown or JSON fallback).'
1154
+ )
1155
+ context_items: list[dict[str, Any]] = Field(
1156
+ ...,
1157
+ alias='contextItems',
1158
+ deprecated=True,
1159
+ description='Deprecated. Always an empty array. Use `context` for composed text (markdown or JSON fallback).',
1160
+ examples=[[]],
1161
+ )
1162
+ original_count: float = Field(
1163
+ ...,
1164
+ alias='originalCount',
1165
+ description='Total context items in the configured scope (before composition strategies).',
1166
+ )
1167
+ selected_count: float = Field(
1168
+ ..., alias='selectedCount', description='Context items the composer kept for this intent.'
1169
+ )
1170
+ session_id: str = Field(
1171
+ ..., alias='sessionId', description='Session id used for this composition.'
1172
+ )
1173
+
1174
+
1175
+ class OrgMemberDto(BaseModel):
1176
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1177
+ user_id: str
1178
+ first_name: str
1179
+ last_name: str
1180
+ email: str
1181
+ image_url: str
1182
+ role: str
1183
+
1184
+
1185
+ class PendingOwnershipTransferDto(BaseModel):
1186
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1187
+ pending_owner_user_id: str = Field(
1188
+ ...,
1189
+ alias='pendingOwnerUserId',
1190
+ description='Clerk user id of the org member who will become owner once they accept.',
1191
+ examples=['user_2abc123def456'],
1192
+ )
1193
+ pending_owner_email: str | None = Field(
1194
+ None,
1195
+ alias='pendingOwnerEmail',
1196
+ description='Email of the pending recipient, resolved from org membership at request time.',
1197
+ examples=['newowner@example.com'],
1198
+ )
1199
+ requested_by_user_id: str = Field(
1200
+ ...,
1201
+ alias='requestedByUserId',
1202
+ description='Clerk user id of the member who requested the transfer (the current owner).',
1203
+ examples=['user_2xyz789ghi012'],
1204
+ )
1205
+ requested_at: str = Field(
1206
+ ...,
1207
+ alias='requestedAt',
1208
+ description='When the transfer was requested.',
1209
+ examples=['2026-06-05T12:00:00.000Z'],
1210
+ )
1211
+
1212
+
1213
+ class ReasoningEffort(str, Enum):
1214
+ none = 'none'
1215
+ minimal = 'minimal'
1216
+ low = 'low'
1217
+ medium = 'medium'
1218
+ high = 'high'
1219
+ xhigh = 'xhigh'
1220
+ max = 'max'
1221
+
1222
+
1223
+ class ResourceLifecycleStatus(str, Enum):
1224
+ draft = 'draft'
1225
+ active = 'active'
1226
+ deleted = 'deleted'
1227
+
1228
+
1229
+ class SearchMemoriesRequestDto(BaseModel):
1230
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1231
+ query: str = Field(
1232
+ ...,
1233
+ description="Search query string (semantic search over the scope's memories).",
1234
+ examples=['user preferences for response style'],
1235
+ )
1236
+ user_id: str | None = Field(
1237
+ None,
1238
+ alias='userId',
1239
+ description='Narrow results to memories tagged with this end-user id.',
1240
+ examples=['user_clerk_X'],
1241
+ )
1242
+ limit: float | None = Field(
1243
+ None,
1244
+ description='Override the default page size for search results (legacy default is 10).',
1245
+ examples=[10],
1246
+ ge=1.0,
1247
+ le=1000.0,
1248
+ )
1249
+
1250
+
1251
+ class SetSupervisionRequestDto(BaseModel):
1252
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1253
+ subordinate_agent_ids: list[float] = Field(
1254
+ ...,
1255
+ alias='subordinateAgentIds',
1256
+ description='Replacement list of subordinate scope ids. The previous list is fully replaced; pass `[]` to clear.',
1257
+ examples=[[17, 23, 91]],
1258
+ )
1259
+
1260
+
1261
+ class SharedUserPermission(str, Enum):
1262
+ use = 'use'
1263
+ manage = 'manage'
1264
+
1265
+
1266
+ class SkillChatRequestDto(BaseModel):
1267
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1268
+ message: str = Field(
1269
+ ...,
1270
+ description='User message sent to the published scope supervisor.',
1271
+ examples=['Summarize open support tickets from last week.'],
1272
+ min_length=1,
1273
+ )
1274
+ model: Model | None = Field(
1275
+ ...,
1276
+ description='Canonical model id for this run (required). Allowed values: claude-sonnet-5, claude-sonnet-4.6, claude-opus-4.8, gpt-5.2, gpt-5.5, gpt-5-mini, gpt-oss-120b, gpt-oss-20b, qwen3-235b-a22b-2507, qwen3-coder, qwen3-32b, deepseek-chat-v3.1, minimax-m2.7, llama-4-maverick, llama-4-scout, llama-3.3-70b-instruct, gemini-3.1-pro-preview, gemini-3-flash-preview, grok-4.3-fast, grok-4.3.',
1277
+ examples=['claude-sonnet-4.6'],
1278
+ )
1279
+
1280
+
1281
+ class SkillChatResponseDto(BaseModel):
1282
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1283
+ content: str = Field(
1284
+ ...,
1285
+ description='Final assistant text for the run.',
1286
+ examples=['There were 12 open tickets last week…'],
1287
+ )
1288
+ thread_id: str = Field(
1289
+ ...,
1290
+ alias='threadId',
1291
+ description='Conversation thread id. For follow-up messages use POST …/conversations/{threadId}/chat (same id as GET …/conversations/{threadId}).',
1292
+ examples=['api-skill-42-550e8400-e29b-41d4-a716-446655440000'],
1293
+ )
1294
+ run_id: str = Field(
1295
+ ...,
1296
+ alias='runId',
1297
+ description='Opaque run id for this chat invocation (for logging and correlation).',
1298
+ examples=['550e8400-e29b-41d4-a716-446655440001'],
1299
+ )
1300
+
1301
+
1302
+ class SkillMcpInterfaceConfigDto(BaseModel):
1303
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1304
+ core_tools: dict[str, Any] | None = Field(
1305
+ None,
1306
+ alias='coreTools',
1307
+ description='Built-in MCP tools (chat, get_context) exposed by this scope.',
1308
+ )
1309
+ mcp_tool_exposure: dict[str, Any] | None = Field(
1310
+ None,
1311
+ alias='mcpToolExposure',
1312
+ description='Outbound tool exposure for MCP clients (subset or all).',
1313
+ )
1314
+
1315
+
1316
+ class SuggestionEventSource(str, Enum):
1317
+ home = 'home'
1318
+
1319
+
1320
+ class SuggestionEventType(str, Enum):
1321
+ shown = 'shown'
1322
+ clicked = 'clicked'
1323
+ dismissed = 'dismissed'
1324
+ submitted = 'submitted'
1325
+
1326
+
1327
+ class SuggestionQuestionDto(BaseModel):
1328
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1329
+ id: str = Field(..., description='Stable suggestion id.')
1330
+ skill_id: float | None = Field(
1331
+ None, description='Numeric scope id this suggestion is scoped to.'
1332
+ )
1333
+ label: str = Field(..., description='Short Home button label.')
1334
+ prompt: str = Field(..., description='Prompt sent when the suggestion is selected.')
1335
+ rationale: str | None = Field(None, description='Reason this suggestion was generated.')
1336
+ metadata: dict[str, Any] | None = Field(
1337
+ None, description='Suggestion metadata for diagnostics and ranking.'
1338
+ )
1339
+
1340
+
1341
+ class SupervisionDto(BaseModel):
1342
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1343
+ supervisor_agent_id: float = Field(
1344
+ ...,
1345
+ alias='supervisorAgentId',
1346
+ description='Numeric id of the scope that supervises the listed subordinates. Echoes the `:id` from the URL path.',
1347
+ examples=[42],
1348
+ )
1349
+ subordinate_agent_ids: list[float] = Field(
1350
+ ...,
1351
+ alias='subordinateAgentIds',
1352
+ description='Numeric ids of the scopes supervised by `supervisorAgentId`. The order is preserved across writes and reads.',
1353
+ examples=[[17, 23, 91]],
1354
+ )
1355
+
1356
+
1357
+ class ToggleAgentDto(BaseModel):
1358
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1359
+ active: bool = Field(
1360
+ ...,
1361
+ description='Target enabled state. `true` enables the workflow schedule; `false` disables it.',
1362
+ examples=[True],
1363
+ )
1364
+
1365
+
1366
+ class ToolsetToolDto(BaseModel):
1367
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1368
+ id: str = Field(
1369
+ ...,
1370
+ description='Stable id of the tool (matches the registry key on the workflow runtime).',
1371
+ examples=['web_search'],
1372
+ )
1373
+ enabled: bool | None = Field(
1374
+ None,
1375
+ description='Whether this tool is enabled for the scope. Defaults to true when absent.',
1376
+ examples=[True],
1377
+ )
1378
+ config: dict[str, Any] | None = Field(
1379
+ None,
1380
+ description='Free-form tool-specific configuration (e.g. allowlists). Schema varies per tool.',
1381
+ examples=[{'max_results': 5}],
1382
+ )
1383
+
1384
+
1385
+ class TransferOwnershipDto(BaseModel):
1386
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1387
+ new_owner_user_id: str = Field(
1388
+ ...,
1389
+ alias='newOwnerUserId',
1390
+ description='Clerk user id of the org member who will become the new owner.',
1391
+ examples=['user_2abc123def456'],
1392
+ )
1393
+
1394
+
1395
+ class TriggerType(str, Enum):
1396
+ schedule = 'schedule'
1397
+ webhook = 'webhook'
1398
+ api = 'api'
1399
+ slack = 'slack'
1400
+ manual = 'manual'
1401
+
1402
+
1403
+ class TriggerEvaluationRunResponseDto(BaseModel):
1404
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1405
+ run_id: str = Field(..., alias='runId', description='The created run ID')
1406
+ workflow_id: str | None = Field(
1407
+ None, alias='workflowId', description='Workflow identifier for the run'
1408
+ )
1409
+
1410
+
1411
+ class Frequency(str, Enum):
1412
+ hourly = 'hourly'
1413
+ daily = 'daily'
1414
+ weekly = 'weekly'
1415
+ monthly = 'monthly'
1416
+ custom = 'custom'
1417
+
1418
+
1419
+ class Weekday(str, Enum):
1420
+ monday = 'monday'
1421
+ tuesday = 'tuesday'
1422
+ wednesday = 'wednesday'
1423
+ thursday = 'thursday'
1424
+ friday = 'friday'
1425
+ saturday = 'saturday'
1426
+ sunday = 'sunday'
1427
+
1428
+
1429
+ class TriggerScheduleDto(BaseModel):
1430
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1431
+ frequency: Frequency = Field(..., description='Cadence of the schedule.', examples=['daily'])
1432
+ time_of_day: str | None = Field(
1433
+ None,
1434
+ description='Time of day in 24-hour HH:MM format. Required for hourly/daily/weekly/monthly; ignored for custom.',
1435
+ examples=['09:00'],
1436
+ pattern='^([01]\\d|2[0-3]):[0-5]\\d$',
1437
+ )
1438
+ timezone: str = Field(..., description='IANA timezone identifier.', examples=['UTC'])
1439
+ weekdays: list[Weekday] | None = Field(
1440
+ None,
1441
+ description='Required for weekly schedules. Lowercase day names.',
1442
+ examples=[['monday', 'wednesday', 'friday']],
1443
+ )
1444
+ day_of_month: float | None = Field(
1445
+ None,
1446
+ description='Required for monthly schedules. Calendar day 1-31.',
1447
+ examples=[15],
1448
+ ge=1.0,
1449
+ le=31.0,
1450
+ )
1451
+ cron_expressions: list[str] | None = Field(
1452
+ None,
1453
+ description='Required for custom schedules. Each entry is a 5-field POSIX cron expression.',
1454
+ examples=[['0 9 * * 1-5']],
1455
+ )
1456
+ cron_description: str | None = Field(
1457
+ None,
1458
+ description='Human-readable description of the custom schedule. Required when frequency=custom.',
1459
+ examples=['Weekdays at 9am'],
1460
+ )
1461
+
1462
+
1463
+ class UpdateAgentInterfaceDto(BaseModel):
1464
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1465
+ name: str | None = Field(
1466
+ None,
1467
+ description='New display name.',
1468
+ examples=['Internal MCP v2'],
1469
+ max_length=200,
1470
+ min_length=1,
1471
+ )
1472
+ config: dict[str, Any] | None = Field(
1473
+ None,
1474
+ description='New config payload (interface-type-specific). Free-form JSONB. Replaces the prior config.',
1475
+ examples=[{}],
1476
+ )
1477
+
1478
+
1479
+ class UpdateContextItemDto(BaseModel):
1480
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1481
+ context_type: str | None = Field(
1482
+ None,
1483
+ alias='contextType',
1484
+ description='Required when `content` is supplied — selects which partition to update against. Free-form string (e.g. `note`, `saved_query`).',
1485
+ examples=['note'],
1486
+ )
1487
+ content: dict[str, Any] | None = Field(
1488
+ None, description='Replacement type-specific JSON content. Shape varies by `contextType`.'
1489
+ )
1490
+ description: str | None = Field(
1491
+ None,
1492
+ description='Replacement description text.',
1493
+ examples=['Updated description after review'],
1494
+ )
1495
+ user_feedback: UserFeedback | None = Field(
1496
+ None,
1497
+ alias='userFeedback',
1498
+ description='User-supplied verification verdict.',
1499
+ examples=['positive'],
1500
+ )
1501
+ topics: list[str] | None = Field(
1502
+ None,
1503
+ description='Replacement topic tags. Pass `[]` to clear all tags.',
1504
+ examples=[['analytics', 'verified']],
1505
+ )
1506
+
1507
+
1508
+ class UpdateCustomContextItemDto(BaseModel):
1509
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1510
+ name: str | None = Field(
1511
+ None, description='Replacement display name.', examples=['Acme renewal contract']
1512
+ )
1513
+ entity_type: str | None = Field(
1514
+ None,
1515
+ alias='entityType',
1516
+ description='Replacement customer-defined entity or field type.',
1517
+ examples=['contract'],
1518
+ )
1519
+ description: str | None = Field(
1520
+ None,
1521
+ description='Replacement description.',
1522
+ examples=['Updated internal billing metadata.'],
1523
+ )
1524
+ content: dict[str, Any] | None = Field(
1525
+ None, description='Replacement main textual or structured content.'
1526
+ )
1527
+ url: str | None = Field(
1528
+ None,
1529
+ description='Replacement customer-facing URL.',
1530
+ examples=['https://internal.example.com/contracts/contract-123'],
1531
+ )
1532
+ attributes: list[CustomAttributeDto] | None = Field(
1533
+ None, description='Replacement structured attributes.'
1534
+ )
1535
+ data_type: str | None = Field(
1536
+ None, alias='dataType', description='Replacement field data type.', examples=['timestamp']
1537
+ )
1538
+ value: dict[str, Any] | None = Field(
1539
+ None, description='Replacement representative field value.'
1540
+ )
1541
+ samples: list[dict[str, Any]] | None = Field(
1542
+ None, description='Replacement representative samples.'
1543
+ )
1544
+ raw: dict[str, Any] | None = Field(
1545
+ None, description='Replacement customer-specific raw fields.'
1546
+ )
1547
+ topics: list[str] | None = Field(
1548
+ None,
1549
+ description='Replacement topic tags. Pass `[]` to clear all tags.',
1550
+ examples=[['billing', 'verified']],
1551
+ )
1552
+
1553
+
1554
+ class UpdateMemoryRequestDto(BaseModel):
1555
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1556
+ memory: str | None = Field(
1557
+ None,
1558
+ description='Replacement memory text. Optional — supply when revising the text.',
1559
+ examples=['User prefers concise bullet-point summaries.'],
1560
+ )
1561
+ metadata: dict[str, Any] | None = Field(
1562
+ None,
1563
+ description='Replacement metadata bag. Optional.',
1564
+ examples=[{'topic': 'preferences', 'confidence': 'high'}],
1565
+ )
1566
+
1567
+
1568
+ class UsageBucketDto(BaseModel):
1569
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1570
+ bucket: str = Field(..., description='ISO8601 timestamp at the start of the bucket.')
1571
+ model: str | None = Field(
1572
+ None,
1573
+ description='Canonicalised LLM model name. Present only when grouping by model (where it equals `group_value`); omitted on scope/workflow/interface breakdowns, where the grouped value lives in `group_value`.',
1574
+ )
1575
+ group_value: str = Field(
1576
+ ..., description='The grouped dimension value (scope/workflow id, interface, or model).'
1577
+ )
1578
+ call_count: float = Field(
1579
+ ..., description='Number of LLM_CALL events in this bucket for this model.'
1580
+ )
1581
+ input_tokens: float = Field(..., description='Sum of input (prompt) tokens.')
1582
+ output_tokens: float = Field(..., description='Sum of output (response) tokens.')
1583
+ credits: float = Field(..., description='Credits consumed in this bucket.')
1584
+
1585
+
1586
+ class UsageTotalsDto(BaseModel):
1587
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1588
+ call_count: float
1589
+ input_tokens: float
1590
+ output_tokens: float
1591
+ credits: float = Field(
1592
+ ..., description='Total credits consumed across all buckets in the window.'
1593
+ )
1594
+
1595
+
1596
+ class WorkflowEdgeDto(BaseModel):
1597
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1598
+ id: str = Field(..., description='Stable edge id, unique within the graph.', examples=['e1'])
1599
+ source: str = Field(..., description='Source node id.', examples=['1'])
1600
+ target: str = Field(..., description='Target node id.', examples=['2'])
1601
+ source_handle: str | None = Field(
1602
+ None,
1603
+ alias='sourceHandle',
1604
+ description='Source port handle (e.g. a condition branch). Omit for a single-output node.',
1605
+ examples=['branch_0'],
1606
+ )
1607
+
1608
+
1609
+ class WorkflowNodePositionDto(BaseModel):
1610
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1611
+ x: float = Field(..., examples=[0])
1612
+ y: float = Field(..., examples=[50])
1613
+
1614
+
1615
+ class WorkflowNodeType(str, Enum):
1616
+ start = 'start'
1617
+ action = 'action'
1618
+ condition = 'condition'
1619
+ agent = 'agent'
1620
+ human_approval = 'humanApproval'
1621
+
1622
+
1623
+ class ActiveConversationRunStatus(str, Enum):
1624
+ queued = 'queued'
1625
+ pending = 'pending'
1626
+ running = 'running'
1627
+
1628
+
1629
+ class ActiveRunsBySessionDto(BaseModel):
1630
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1631
+ session_ids: list[str] = Field(
1632
+ ...,
1633
+ alias='sessionIds',
1634
+ description='Conversation thread ids to check for non-terminal runs.',
1635
+ max_length=100,
1636
+ )
1637
+
1638
+
1639
+ class Version(str, Enum):
1640
+ published = 'published'
1641
+ draft = 'draft'
1642
+
1643
+
1644
+ class StreamProtocolVersion(float, Enum):
1645
+ number_2 = 2
1646
+
1647
+
1648
+ class CancelRunDto(BaseModel):
1649
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1650
+ pass
1651
+
1652
+
1653
+ class DocumentAttachmentDto(BaseModel):
1654
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1655
+ file_name: str = Field(..., alias='fileName', description='Original file name.')
1656
+ parsed_content: str | None = Field(None, alias='parsedContent')
1657
+ upload_id: str | None = Field(None, alias='uploadId')
1658
+ mime_type: str | None = Field(None, alias='mimeType')
1659
+ original_size: float | None = Field(None, alias='originalSize')
1660
+ storage_file_name: str | None = Field(None, alias='storageFileName')
1661
+ raw_content_s3_key: str | None = Field(None, alias='rawContentS3Key')
1662
+ size_bytes: float | None = Field(None, alias='sizeBytes')
1663
+ summary: str | None = None
1664
+
1665
+
1666
+ class EditQueuedRunDto(BaseModel):
1667
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1668
+ pass
1669
+
1670
+
1671
+ class ErrorEnvelopeDto1(BaseModel):
1672
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1673
+ code: ApiErrorCode = Field(..., description='Modus-specific machine code.')
1674
+ status: ApiErrorStatus = Field(..., description='Canonical status string for the error.')
1675
+ message: str = Field(..., examples=['Run was not found or you lack permission.'])
1676
+ request_id: str = Field(..., alias='requestId', examples=['req_01HQ7K8ABCDEFGHIJKLMNOPQRS'])
1677
+ info: dict[str, Any] | None = Field(
1678
+ None,
1679
+ description='Optional domain-specific context. Shape varies per endpoint.',
1680
+ examples=[{'runId': 'run_abc123'}],
1681
+ )
1682
+
1683
+
1684
+ class ErrorResponseDto1(BaseModel):
1685
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1686
+ error: ErrorEnvelopeDto1
1687
+
1688
+
1689
+ class ImageAttachmentDto(BaseModel):
1690
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1691
+ data: str | None = None
1692
+ mime_type: str | None = Field(None, alias='mimeType')
1693
+ name: str | None = None
1694
+ s3_key: str | None = Field(None, alias='s3Key')
1695
+ upload_id: str | None = Field(None, alias='uploadId')
1696
+
1697
+
1698
+ class InterruptRunDto(BaseModel):
1699
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1700
+ pass
1701
+
1702
+
1703
+ class Decision(str, Enum):
1704
+ approve = 'approve'
1705
+ deny = 'deny'
1706
+ connected = 'connected'
1707
+ cancelled = 'cancelled'
1708
+
1709
+
1710
+ class RunReasoningEffort(str, Enum):
1711
+ none = 'none'
1712
+ minimal = 'minimal'
1713
+ low = 'low'
1714
+ medium = 'medium'
1715
+ high = 'high'
1716
+ xhigh = 'xhigh'
1717
+ max = 'max'
1718
+
1719
+
1720
+ class RunSource(str, Enum):
1721
+ home = 'home'
1722
+ agent_settings = 'agent_settings'
1723
+ agent = 'agent'
1724
+ api = 'api'
1725
+ modus_api = 'modus_api'
1726
+ mcp = 'mcp'
1727
+ slack = 'slack'
1728
+ slack_dm = 'slack_dm'
1729
+ teams = 'teams'
1730
+ context_chat = 'context_chat'
1731
+ other = 'other'
1732
+
1733
+
1734
+ class SupplementalContextSource(str, Enum):
1735
+ slack = 'slack'
1736
+ teams = 'teams'
1737
+
1738
+
1739
+ class UserContextDto(BaseModel):
1740
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1741
+ email: str | None = Field(None, description='End-user email for personalization.')
1742
+ name: str | None = Field(None, description='End-user display name.')
1743
+ timezone: str | None = Field(None, description='IANA timezone, e.g. America/New_York.')
1744
+ user_id: str | None = Field(
1745
+ None, alias='userId', description='User id for system/PAT runs (usage attribution).'
1746
+ )
1747
+
1748
+
1749
+ class WorkflowActionSource(str, Enum):
1750
+ agent = 'agent'
1751
+ api = 'api'
1752
+ other = 'other'
1753
+
1754
+
1755
+ class AddAgentInterfaceDto(BaseModel):
1756
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1757
+ type: AgentInterfaceType | None = Field(
1758
+ ...,
1759
+ description='Interface type. Only `slack`, `mcp`, and `teams` are accepted.',
1760
+ examples=['mcp'],
1761
+ )
1762
+ name: str | None = Field(
1763
+ ...,
1764
+ description='Display name for the interface.',
1765
+ examples=['Internal MCP'],
1766
+ max_length=200,
1767
+ min_length=1,
1768
+ )
1769
+ config: dict[str, Any] | None = Field(
1770
+ None,
1771
+ description='Initial config payload (interface-type-specific). Free-form JSONB.',
1772
+ examples=[{}],
1773
+ )
1774
+
1775
+
1776
+ class AgentAccessConfigDto(BaseModel):
1777
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1778
+ visibility: Visibility = Field(
1779
+ ...,
1780
+ description='Visibility tier. `shared` applies the group-permission map; `private` ignores groups and uses owner + sharedWith for access.',
1781
+ examples=['shared'],
1782
+ )
1783
+ group_permissions: dict[str, AgentGroupPermissionDto] = Field(
1784
+ ...,
1785
+ alias='groupPermissions',
1786
+ description='Map of group UUID -> { use, manage } booleans. Empty object when visibility is `private`.',
1787
+ examples=[{'group_eng_uuid': {'use': True, 'manage': False}}],
1788
+ )
1789
+ shared_with: list[AgentSharedUserDto] = Field(
1790
+ ...,
1791
+ alias='sharedWith',
1792
+ description='Per-user share entries used for private-visibility workflows.',
1793
+ examples=[[]],
1794
+ )
1795
+ owner_user_id: str | None = Field(
1796
+ None,
1797
+ alias='ownerUserId',
1798
+ description='Clerk user id of the workflow owner. Set on first write for private workflows.',
1799
+ examples=['user_2abc'],
1800
+ )
1801
+ owner_email: str | None = Field(
1802
+ None,
1803
+ alias='ownerEmail',
1804
+ description='Lowercased email of the workflow owner. Used by private-workflow ACL when owner email matches.',
1805
+ examples=['alice@example.com'],
1806
+ )
1807
+
1808
+
1809
+ class AgentDto(BaseModel):
1810
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1811
+ id: float = Field(
1812
+ ...,
1813
+ description='Numeric workflow id (stable per-org; not reused after delete).',
1814
+ examples=[42],
1815
+ )
1816
+ slug: str = Field(
1817
+ ...,
1818
+ description='URL-safe slug used in human-readable links. Unique per org.',
1819
+ examples=['customer-churn-agent-a3f'],
1820
+ )
1821
+ name: str | None = Field(
1822
+ ...,
1823
+ description='Display name of the workflow. Shown in the builder and in run logs.',
1824
+ examples=['Customer Churn Analyzer'],
1825
+ )
1826
+ description: str | None = Field(
1827
+ None,
1828
+ description='Optional one-paragraph description of what this workflow does.',
1829
+ examples=['Predicts churn risk for a customer given a 90-day usage window.'],
1830
+ )
1831
+ status: ResourceLifecycleStatus = Field(
1832
+ ...,
1833
+ description='Lifecycle status. `draft` = never deployed. `active` = deployed. `deleted` = soft-deleted.',
1834
+ examples=['active'],
1835
+ )
1836
+ type: AgentType | None = Field(
1837
+ ...,
1838
+ description='Type of workflow. `task` = single-step scope orchestration; `workflow` = multi-step graph.',
1839
+ examples=['task'],
1840
+ )
1841
+ org_uuid: str = Field(
1842
+ ...,
1843
+ alias='orgUuid',
1844
+ description='Org UUID this workflow belongs to. Matches the caller’s principal.',
1845
+ examples=['00000000-0000-0000-0000-000000000001'],
1846
+ )
1847
+ active_variation_id: str | None = Field(
1848
+ None,
1849
+ alias='activeVariationId',
1850
+ description='Active (deployed) variation id. Null until the workflow is first deployed.',
1851
+ examples=['00000000-0000-4000-a000-000000000100'],
1852
+ )
1853
+ draft_variation_id: str | None = Field(
1854
+ None,
1855
+ alias='draftVariationId',
1856
+ description='Most recent draft variation id. Null when there is no draft pending.',
1857
+ examples=['00000000-0000-4000-a000-000000000101'],
1858
+ )
1859
+ has_unpublished_changes: bool = Field(
1860
+ ...,
1861
+ alias='hasUnpublishedChanges',
1862
+ description='True when the draft variation differs from the active variation (deploy would publish changes).',
1863
+ examples=[False],
1864
+ )
1865
+ is_enabled: bool = Field(
1866
+ ...,
1867
+ alias='isEnabled',
1868
+ description='Whether the workflow’s schedule is currently active. Toggle via the workflow schedule API.',
1869
+ examples=[True],
1870
+ )
1871
+ access_config: AgentAccessConfigDto = Field(
1872
+ ...,
1873
+ alias='accessConfig',
1874
+ description='Access configuration — who in the org can use / manage this workflow.',
1875
+ )
1876
+ pending_ownership_transfer: (
1877
+ PendingOwnershipTransferDto | None
1878
+ ) = (
1879
+ Field(None, alias='pendingOwnershipTransfer', description='Pending ownership transfer awaiting recipient acceptance. Absent when no request is in flight.')
1880
+ )
1881
+ variation: AgentVariationDto | None = Field(
1882
+ None,
1883
+ description='Variation-detail payload (`trigger`, `workflowStructure`, `agentSelection`) for the requested view. Present on detail responses; absent on list rows.',
1884
+ )
1885
+ created_at: str = Field(
1886
+ ...,
1887
+ alias='createdAt',
1888
+ description='Creation timestamp.',
1889
+ examples=['2026-05-01T10:00:00.000Z'],
1890
+ )
1891
+ updated_at: str = Field(
1892
+ ...,
1893
+ alias='updatedAt',
1894
+ description='Most recent update timestamp.',
1895
+ examples=['2026-05-11T10:00:00.000Z'],
1896
+ )
1897
+ deleted_at: str | None = Field(
1898
+ None,
1899
+ alias='deletedAt',
1900
+ description='Soft-delete timestamp. Null for active workflows.',
1901
+ examples=[None],
1902
+ )
1903
+ can_manage: bool = Field(
1904
+ ...,
1905
+ alias='canManage',
1906
+ description='Whether the requesting principal can manage (edit/delete/deploy/toggle) this workflow. Derived server-side from the principal + accessConfig. Always present on every Workflow response.',
1907
+ examples=[True],
1908
+ )
1909
+ can_use: bool = Field(
1910
+ ...,
1911
+ alias='canUse',
1912
+ description='Whether the requesting principal can use (run, view history of) this workflow. Derived server-side from the principal + accessConfig. Always present on every Workflow response.',
1913
+ examples=[True],
1914
+ )
1915
+ manage_denial: ManageDenial | None = Field(
1916
+ ...,
1917
+ alias='manageDenial',
1918
+ description='Why `canManage` is false, for client-facing guidance: `needs_group_manage` (shared, but no group you belong to grants Manage) or `not_owner` (private, and you are not the owner). `null` when `canManage` is true. Derived server-side from the principal + accessConfig.',
1919
+ examples=['needs_group_manage'],
1920
+ )
1921
+
1922
+
1923
+ class AgentInterfaceDto(BaseModel):
1924
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1925
+ id: str = Field(
1926
+ ...,
1927
+ description='Interface row id (UUID).',
1928
+ examples=['00000000-0000-4000-a000-000000000300'],
1929
+ )
1930
+ agent_id: float = Field(..., alias='agentId', description='Parent workflow id.', examples=[42])
1931
+ type: AgentInterfaceType | None = Field(
1932
+ ...,
1933
+ description='Interface type. `slack` and `teams` deliver chat triggers; `mcp` exposes the workflow as an MCP server.',
1934
+ examples=['mcp'],
1935
+ )
1936
+ name: str | None = Field(
1937
+ ...,
1938
+ description='Display name for the interface (shown in the SPA).',
1939
+ examples=['Internal MCP'],
1940
+ )
1941
+ config: dict[str, Any] = Field(
1942
+ ...,
1943
+ description='Interface-type-specific configuration (e.g. webhook url, MCP token references). Free-form JSONB.',
1944
+ examples=[{}],
1945
+ )
1946
+ created_at: str = Field(
1947
+ ...,
1948
+ alias='createdAt',
1949
+ description='Creation timestamp.',
1950
+ examples=['2026-05-01T10:00:00.000Z'],
1951
+ )
1952
+ updated_at: str = Field(
1953
+ ...,
1954
+ alias='updatedAt',
1955
+ description='Most recent update timestamp.',
1956
+ examples=['2026-05-11T10:00:00.000Z'],
1957
+ )
1958
+
1959
+
1960
+ class BatchCreateCustomContextItemsResponseDto(BaseModel):
1961
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1962
+ context_items: list[CreatedCustomContextItemResponseDto] = Field(
1963
+ ...,
1964
+ alias='contextItems',
1965
+ description='Custom context items created or updated by the batch.',
1966
+ )
1967
+
1968
+
1969
+ class ConversationMessageDto(BaseModel):
1970
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
1971
+ type: ConversationMessageType | None = Field(
1972
+ ...,
1973
+ description='Message role. `human` and `ai` cover the user-visible turns; `system`, `tool`, and `unknown` are surfaced for completeness.',
1974
+ examples=['human'],
1975
+ )
1976
+ content: str = Field(
1977
+ ...,
1978
+ description='Message content. Usually a string for human turns; AI turns from newer LangChain versions may carry an array of content blocks (e.g. `[{type:"text",text:"…"}]`) instead. Consumers should handle both shapes.',
1979
+ examples=['Run the churn analysis for last 30 days.'],
1980
+ )
1981
+ id: str | None = Field(
1982
+ None,
1983
+ description='Stable identifier for this message turn, when available.',
1984
+ examples=['msg_01HF8X3Z2K8E0'],
1985
+ )
1986
+ tool_calls: list[Any] | None = Field(
1987
+ None,
1988
+ alias='toolCalls',
1989
+ description='Tool invocations emitted by this message (AI turns). Shape mirrors the LangChain tool-call envelope.',
1990
+ )
1991
+ tool_call_id: str | None = Field(
1992
+ None,
1993
+ alias='toolCallId',
1994
+ description='Tool call id this message responds to (for `tool` turns).',
1995
+ )
1996
+
1997
+
1998
+ class CreateCustomContextItemDto(BaseModel):
1999
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2000
+ kind: CustomContextItemKind = Field(
2001
+ ..., description='Shape of custom context item to create.', examples=['entity']
2002
+ )
2003
+ source_id: str = Field(
2004
+ ...,
2005
+ alias='sourceId',
2006
+ description='Stable identifier for the customer-defined source.',
2007
+ examples=['billing-db'],
2008
+ )
2009
+ source_name: str | None = Field(
2010
+ None,
2011
+ alias='sourceName',
2012
+ description='Display name for the customer-defined source.',
2013
+ examples=['Billing database'],
2014
+ )
2015
+ collection_id: str | None = Field(
2016
+ None,
2017
+ alias='collectionId',
2018
+ description='Stable identifier for the collection inside the source.',
2019
+ examples=['contracts'],
2020
+ )
2021
+ collection_name: str | None = Field(
2022
+ None,
2023
+ alias='collectionName',
2024
+ description='Display name for the collection.',
2025
+ examples=['Contracts'],
2026
+ )
2027
+ external_id: str | None = Field(
2028
+ None,
2029
+ alias='externalId',
2030
+ description='Stable identifier for the entity inside the collection.',
2031
+ examples=['contract-123'],
2032
+ )
2033
+ field_name: str | None = Field(
2034
+ None,
2035
+ alias='fieldName',
2036
+ description='Field name for field-level custom context.',
2037
+ examples=['renewalDate'],
2038
+ )
2039
+ name: str | None = Field(
2040
+ None, description='Display name for the item.', examples=['Acme renewal contract']
2041
+ )
2042
+ entity_type: str | None = Field(
2043
+ None,
2044
+ alias='entityType',
2045
+ description='Customer-defined entity or field type.',
2046
+ examples=['contract'],
2047
+ )
2048
+ description: str | None = Field(
2049
+ None,
2050
+ description='Human-readable description.',
2051
+ examples=['Enterprise contract renewal metadata from the internal billing system.'],
2052
+ )
2053
+ content: dict[str, Any] | None = Field(
2054
+ None, description='Main textual or structured content for the custom item.'
2055
+ )
2056
+ url: str | None = Field(
2057
+ None,
2058
+ description='Customer-facing URL for the source object, when available.',
2059
+ examples=['https://internal.example.com/contracts/contract-123'],
2060
+ )
2061
+ attributes: list[CustomAttributeDto] | None = Field(
2062
+ None, description='Structured attributes for entity-level custom context.'
2063
+ )
2064
+ data_type: str | None = Field(
2065
+ None,
2066
+ alias='dataType',
2067
+ description='Field data type for field-level custom context.',
2068
+ examples=['timestamp'],
2069
+ )
2070
+ value: dict[str, Any] | None = Field(
2071
+ None, description='Representative value for field-level custom context.'
2072
+ )
2073
+ samples: list[dict[str, Any]] | None = Field(
2074
+ None, description='Representative samples for entity sample context.'
2075
+ )
2076
+ raw: dict[str, Any] | None = Field(
2077
+ None,
2078
+ description='Customer-specific fields that should be retained but are not part of the normalized contract.',
2079
+ )
2080
+ topics: list[str] | None = Field(
2081
+ None, description='Topic tags for filtering.', examples=[['billing', 'renewals']]
2082
+ )
2083
+ idempotency_key: str | None = Field(
2084
+ None,
2085
+ alias='idempotencyKey',
2086
+ description='Optional stable key used to make single-item creates idempotent.',
2087
+ examples=['billing-db/contracts/contract-123'],
2088
+ )
2089
+ access: AccessPolicyDto | None = None
2090
+
2091
+
2092
+ class EvaluationCadenceDto(BaseModel):
2093
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2094
+ frequency: EvaluationCadenceFrequency | None = Field(None, description='Schedule frequency')
2095
+ time_of_day: str | None = Field(
2096
+ None, alias='timeOfDay', description='Time of day in HH:MM format', examples=['09:00']
2097
+ )
2098
+ timezone: str | None = Field(None, description='IANA timezone', examples=['America/New_York'])
2099
+ weekdays: list[str] | None = Field(
2100
+ None, description='Days of week for weekly frequency', examples=[['MONDAY', 'WEDNESDAY']]
2101
+ )
2102
+ day_of_month: float | None = Field(
2103
+ None, alias='dayOfMonth', description='Day of month for monthly frequency', ge=1.0, le=31.0
2104
+ )
2105
+ cron_expression: str | None = Field(
2106
+ None,
2107
+ alias='cronExpression',
2108
+ description='Cron expression for custom frequency',
2109
+ examples=['0 9 * * 1-5'],
2110
+ )
2111
+
2112
+
2113
+ class EvaluationChannelsDto(BaseModel):
2114
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2115
+ email: bool = Field(..., description='Enable email notifications')
2116
+ slack: EvaluationSlackChannelDto | None = Field(
2117
+ None, description='Slack notification configuration'
2118
+ )
2119
+
2120
+
2121
+ class EvaluationNotificationsDto(BaseModel):
2122
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2123
+ recipients: list[EvaluationRecipientDto] = Field(..., description='Notification recipients')
2124
+ channels: EvaluationChannelsDto = Field(..., description='Notification channels')
2125
+
2126
+
2127
+ class EvaluationRunDto(BaseModel):
2128
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2129
+ id: str = Field(..., description='Run ID')
2130
+ skill_id: float | None = Field(..., alias='skillId', description='Scope ID')
2131
+ trigger: EvaluationRunTrigger | None = Field(..., description='How the run was triggered')
2132
+ status: EvaluationRunStatus = Field(..., description='Run status')
2133
+ started_at: str = Field(..., alias='startedAt', description='When the run started')
2134
+ finished_at: dict[str, Any] | None = Field(
2135
+ None, alias='finishedAt', description='When the run finished'
2136
+ )
2137
+ total_cases: float = Field(
2138
+ ..., alias='totalCases', description='Total number of evaluation cases'
2139
+ )
2140
+ passed_cases: float = Field(..., alias='passedCases', description='Number of passed cases')
2141
+ failed_cases: float = Field(..., alias='failedCases', description='Number of failed cases')
2142
+ avg_score: dict[str, Any] | None = Field(
2143
+ None, alias='avgScore', description='Average score (0-100)'
2144
+ )
2145
+ is_regression: bool = Field(
2146
+ ..., alias='isRegression', description='Whether this run detected a regression'
2147
+ )
2148
+ judge_model: str | None = Field(None, alias='judgeModel', description='Judge model used')
2149
+ error_message: str | None = Field(
2150
+ None, alias='errorMessage', description='Error message if failed'
2151
+ )
2152
+
2153
+
2154
+ class ListAgentInterfacesResponseDto(BaseModel):
2155
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2156
+ interfaces: list[AgentInterfaceDto] = Field(
2157
+ ..., description='All interfaces attached to the workflow (in creation order).'
2158
+ )
2159
+ next_page_token: str | None = Field(
2160
+ ...,
2161
+ alias='nextPageToken',
2162
+ description='Token for the next page, or null when there are no more results.',
2163
+ )
2164
+
2165
+
2166
+ class ListAgentsResponseDto(BaseModel):
2167
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2168
+ agents: list[AgentDto] = Field(
2169
+ ...,
2170
+ description='Page of workflows the caller can at least `use`. Workflows the caller cannot see are filtered out (not enumerated).',
2171
+ )
2172
+ next_page_token: str | None = Field(
2173
+ ...,
2174
+ alias='nextPageToken',
2175
+ description='Opaque token for the next page; `null` when this was the last page. Pass as `pageToken` on the next request.',
2176
+ examples=['eyJsYXN0SWQiOjQyfQ'],
2177
+ )
2178
+
2179
+
2180
+ class ListEvaluationRunsResponseDto(BaseModel):
2181
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2182
+ runs: list[EvaluationRunDto]
2183
+ next_page_token: str | None = Field(
2184
+ None, alias='nextPageToken', description='Token for next page'
2185
+ )
2186
+
2187
+
2188
+ class ListMemberGroupsResponseDto(BaseModel):
2189
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2190
+ groups: list[MemberGroupDto]
2191
+ next_page_token: str | None = Field(..., alias='nextPageToken')
2192
+
2193
+
2194
+ class ListMemoriesResponseDto(BaseModel):
2195
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2196
+ memories: list[MemoryDto] = Field(..., description='Memories belonging to the scope.')
2197
+ next_page_token: str | None = Field(
2198
+ ...,
2199
+ alias='nextPageToken',
2200
+ description='Opaque token for the next page; `null` when this was the last page. Pass as `pageToken` on the next request.',
2201
+ examples=['eyJvZmZzZXQiOjI1LCJwYWdlU2l6ZSI6MjV9'],
2202
+ )
2203
+
2204
+
2205
+ class ListOrgMembersResponseDto(BaseModel):
2206
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2207
+ members: list[OrgMemberDto]
2208
+ next_page_token: str | None = Field(..., alias='nextPageToken')
2209
+
2210
+
2211
+ class ListSuggestionQuestionsResponseDto(BaseModel):
2212
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2213
+ suggestions: list[SuggestionQuestionDto]
2214
+ next_page_token: str | None = Field(
2215
+ ...,
2216
+ alias='nextPageToken',
2217
+ description='Opaque token for the next page; `null` when this was the last page. Pass as `pageToken` on the next request.',
2218
+ examples=['eyJvZmZzZXQiOjUsInBhZ2VTaXplIjo1fQ'],
2219
+ )
2220
+
2221
+
2222
+ class ListUsageResponseDto(BaseModel):
2223
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2224
+ org_id: str = Field(..., description='Organization id (`org_xxx`) the result is scoped to.')
2225
+ since: str
2226
+ until: str
2227
+ rollup: Rollup
2228
+ group_by: GroupBy = Field(..., description='Dimension that was grouped by in this response.')
2229
+ buckets: list[UsageBucketDto]
2230
+ totals: UsageTotalsDto
2231
+
2232
+
2233
+ class LookupContextItemResponseDto(BaseModel):
2234
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2235
+ item: LookupContextItemRowDto | None = Field(
2236
+ ...,
2237
+ description="The matched row, or null when no row in the caller's tenant matches the supplied `(contextType, dataPath)`.",
2238
+ )
2239
+
2240
+
2241
+ class ModelSettingsDto(BaseModel):
2242
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2243
+ reasoning_effort: ReasoningEffort | None = Field(
2244
+ None,
2245
+ alias='reasoningEffort',
2246
+ description='Optional reasoning effort for models that support it.',
2247
+ )
2248
+ context_window: float | None = Field(
2249
+ None, alias='contextWindow', description='Selected model context window in tokens.', ge=1.0
2250
+ )
2251
+
2252
+
2253
+ class PatchSkillMcpConfigDto(BaseModel):
2254
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2255
+ config: SkillMcpInterfaceConfigDto = Field(
2256
+ ...,
2257
+ description='Full MCP interface config to apply live on the published scope (and mirrored to draft when forked).',
2258
+ )
2259
+
2260
+
2261
+ class PatchSkillMcpConfigResponseDto(BaseModel):
2262
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2263
+ config: SkillMcpInterfaceConfigDto = Field(
2264
+ ..., description='Sanitized MCP config now stored on the published variation.'
2265
+ )
2266
+
2267
+
2268
+ class RecordSuggestionEventDto(BaseModel):
2269
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2270
+ event_type: SuggestionEventType = Field(
2271
+ ..., description='First-party Home suggestion interaction.', examples=['clicked']
2272
+ )
2273
+ source: SuggestionEventSource | None = Field(
2274
+ None, description='Product surface that emitted the event.', examples=['home']
2275
+ )
2276
+ skill_id: float | None = Field(None, description='Selected Home scope id when known.')
2277
+ thread_id: str | None = Field(
2278
+ None, description='Conversation thread id when the event is tied to a chat.'
2279
+ )
2280
+ metadata: dict[str, Any] | None = Field(None, description='Event metadata.')
2281
+
2282
+
2283
+ class SharedUserDto(BaseModel):
2284
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2285
+ email: str = Field(
2286
+ ...,
2287
+ description='Lowercased email of a user explicitly granted access to a private scope.',
2288
+ examples=['alice@example.com'],
2289
+ )
2290
+ added_at: str | None = Field(
2291
+ None,
2292
+ alias='addedAt',
2293
+ description='ISO-8601 timestamp at which this user was added to the share list.',
2294
+ examples=['2026-05-01T10:00:00Z'],
2295
+ )
2296
+ added_by: str | None = Field(
2297
+ None,
2298
+ alias='addedBy',
2299
+ description='Clerk user id of the principal that added this share entry.',
2300
+ examples=['user_2abc'],
2301
+ )
2302
+ user_id: str | None = Field(
2303
+ None,
2304
+ alias='userId',
2305
+ description='Clerk user id of the invited user. Stored for display; access checks use email.',
2306
+ examples=['user_2xyz'],
2307
+ )
2308
+ permission: SharedUserPermission | None = Field(
2309
+ None,
2310
+ description='Per-invitee access level for private scopes. `manage` grants edit / deploy / delete (implies use); `use` (default) grants run-only.',
2311
+ examples=['use'],
2312
+ )
2313
+
2314
+
2315
+ class SkillVariationDto(BaseModel):
2316
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2317
+ expected_output: str = Field(
2318
+ ...,
2319
+ alias='expectedOutput',
2320
+ description='Free-form expected-output prompt that constrains the scope’s reply.',
2321
+ examples=['A 3-bullet summary highlighting churn risk drivers.'],
2322
+ )
2323
+ instructions: list[str] = Field(
2324
+ ...,
2325
+ description='Ordered list of instruction blocks. Each entry is a free-form string the builder rendered into the system prompt.',
2326
+ examples=[['Be concise.', 'Always justify the score.']],
2327
+ )
2328
+ model: str | None = Field(
2329
+ ...,
2330
+ description='Provider-prefixed model id. The orchestrator routes by prefix.',
2331
+ examples=['anthropic/claude-sonnet-4.6'],
2332
+ )
2333
+ model_settings: ModelSettingsDto | None = Field(
2334
+ None,
2335
+ alias='modelSettings',
2336
+ description='Model-specific runtime controls such as reasoning effort and context window.',
2337
+ )
2338
+ toolset: dict[str, Any] = Field(
2339
+ ...,
2340
+ description='Builder-managed toolset descriptor. Map of `{toolName: config}`; opaque to the API surface.',
2341
+ examples=[{'web_search': {'enabled': True}, 'calculator': {'enabled': True}}],
2342
+ )
2343
+ connection_set: list[dict[str, Any]] = Field(
2344
+ ...,
2345
+ alias='connectionSet',
2346
+ description='Connection selections (DBs, integrations) attached to the variation. Each entry is a builder-managed object; opaque here.',
2347
+ )
2348
+ context_selections: list[dict[str, Any]] = Field(
2349
+ ...,
2350
+ alias='contextSelections',
2351
+ description='Context selections attached to the variation. Free-form builder objects.',
2352
+ )
2353
+ evaluations: list[dict[str, Any]] = Field(
2354
+ ...,
2355
+ description='Evaluation entries (task + expected-output pairs) saved for this variation.',
2356
+ )
2357
+ interfaces: list[dict[str, Any]] = Field(
2358
+ ...,
2359
+ description='Interface entries attached to the variation (chat, slack, webhook, etc.). Each is a builder-managed object.',
2360
+ )
2361
+ supervision_subordinate_ids: list[str] = Field(
2362
+ ...,
2363
+ alias='supervisionSubordinateIds',
2364
+ description='IDs of scopes supervised by this scope (when it is a manager). Stringified for wire stability.',
2365
+ examples=[['12', '17']],
2366
+ )
2367
+ supervision_subordinate_descriptions: dict[str, str] = Field(
2368
+ ...,
2369
+ alias='supervisionSubordinateDescriptions',
2370
+ description='Map of subordinateId -> manager-provided description blurb.',
2371
+ examples=[{'12': 'Reads warehouse facts', '17': 'Drafts the report'}],
2372
+ )
2373
+
2374
+
2375
+ class ToolsetDto(BaseModel):
2376
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2377
+ tools: list[ToolsetToolDto] | None = Field(
2378
+ None,
2379
+ description='List of tools the scope may invoke.',
2380
+ examples=[[{'id': 'web_search', 'enabled': True}]],
2381
+ )
2382
+
2383
+
2384
+ class TriggerDto(BaseModel):
2385
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2386
+ trigger_type: TriggerType = Field(
2387
+ ...,
2388
+ description='Trigger kind. Only `schedule` validates its nested payload here; the rest are opaque.',
2389
+ examples=['schedule'],
2390
+ )
2391
+ schedule: TriggerScheduleDto | None = Field(
2392
+ None, description='Schedule details. Required when trigger_type=schedule.'
2393
+ )
2394
+
2395
+
2396
+ class UpdateEvaluationConfigDto(BaseModel):
2397
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2398
+ enabled: bool | None = Field(None, description='Whether scheduled evaluations are enabled')
2399
+ cadence: EvaluationCadenceDto | None = Field(None, description='Schedule cadence configuration')
2400
+ judge_model: str | None = Field(
2401
+ None, alias='judgeModel', description='Model ID for the judge LLM'
2402
+ )
2403
+ judge_guidance: str | None = Field(
2404
+ None, alias='judgeGuidance', description='Custom guidance for the judge LLM'
2405
+ )
2406
+ notifications: EvaluationNotificationsDto | None = Field(
2407
+ None, description='Regression notification settings'
2408
+ )
2409
+
2410
+
2411
+ class WorkflowNodeDto(BaseModel):
2412
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2413
+ id: str = Field(..., description='Stable node id, unique within the graph.', examples=['1'])
2414
+ type: WorkflowNodeType | None = Field(
2415
+ ...,
2416
+ description='Node kind. Determines how the runtime interprets `data`.',
2417
+ examples=['start'],
2418
+ )
2419
+ position: WorkflowNodePositionDto | None = Field(
2420
+ None, description='Canvas position. Optional — preserved for builder layout when present.'
2421
+ )
2422
+ data: dict[str, Any] | None = Field(
2423
+ None,
2424
+ description='Node-type-specific payload (intentionally open — shape varies by `type`). Defaults to `{}`.',
2425
+ examples=[{}],
2426
+ )
2427
+
2428
+
2429
+ class WorkflowStructureDto(BaseModel):
2430
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2431
+ nodes: list[WorkflowNodeDto] | None = Field(
2432
+ None, description='Workflow nodes. Defaults to `[]`.'
2433
+ )
2434
+ edges: list[WorkflowEdgeDto] | None = Field(
2435
+ None, description='Directed edges connecting the nodes. Defaults to `[]`.'
2436
+ )
2437
+
2438
+
2439
+ class ActiveConversationRunDto(BaseModel):
2440
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2441
+ run_id: str = Field(..., alias='runId', description='Run identifier.')
2442
+ session_id: str = Field(..., alias='sessionId', description='Conversation thread id.')
2443
+ status: ActiveConversationRunStatus = Field(..., description='Current non-terminal run status.')
2444
+ message: str | None = Field(None, description='User message that started the run.')
2445
+ created_at: AwareDatetime = Field(..., alias='createdAt', description='Creation timestamp.')
2446
+ updated_at: AwareDatetime = Field(
2447
+ ..., alias='updatedAt', description='Most recent update timestamp.'
2448
+ )
2449
+
2450
+
2451
+ class ActiveRunsBySessionResponseDto(BaseModel):
2452
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2453
+ runs: list[ActiveConversationRunDto]
2454
+
2455
+
2456
+ class ActiveRunsResponseDto(BaseModel):
2457
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2458
+ runs: list[ActiveConversationRunDto]
2459
+ next_page_token: str | None = Field(
2460
+ ...,
2461
+ alias='nextPageToken',
2462
+ description='Opaque token for the next page, or `null` if there are no more active runs.',
2463
+ )
2464
+
2465
+
2466
+ class AttachmentsDto(BaseModel):
2467
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2468
+ images: list[ImageAttachmentDto] | None = None
2469
+ documents: list[DocumentAttachmentDto] | None = None
2470
+
2471
+
2472
+ class RunModelSettingsDto(BaseModel):
2473
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2474
+ reasoning_effort: RunReasoningEffort | None = Field(None, alias='reasoningEffort')
2475
+ context_window: float | None = Field(
2476
+ None, alias='contextWindow', description='Selected model context window in tokens.', ge=1.0
2477
+ )
2478
+
2479
+
2480
+ class SupplementalContextDto(BaseModel):
2481
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2482
+ text: str = Field(
2483
+ ...,
2484
+ description='Background context (e.g. Slack/Teams thread + channel history) to prepend to the system prompt.',
2485
+ )
2486
+ source: SupplementalContextSource = Field(
2487
+ ..., description='Producer that supplied the supplemental context.'
2488
+ )
2489
+
2490
+
2491
+ class WorkflowActionDto(BaseModel):
2492
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2493
+ organization_id: str = Field(
2494
+ ...,
2495
+ alias='organizationId',
2496
+ description="Organization ID the run belongs to. Must match the authenticated principal's org.",
2497
+ )
2498
+ session_id: str = Field(
2499
+ ..., alias='sessionId', description='Client-generated session identifier.'
2500
+ )
2501
+ file_thread_id: str | None = Field(
2502
+ None, alias='fileThreadId', description='File thread ID for document-scoped execution.'
2503
+ )
2504
+ workflow_action: dict[str, Any] = Field(
2505
+ ...,
2506
+ alias='workflowAction',
2507
+ description='Workflow action descriptor: toolId, toolName, aiDescription, runtimeScope, and any action-specific parameters.',
2508
+ )
2509
+ previous_outputs: list[dict[str, Any]] | None = Field(
2510
+ None,
2511
+ alias='previousOutputs',
2512
+ description='Outputs from earlier steps in a multi-step workflow, forwarded to the action runtime.',
2513
+ )
2514
+ user_timezone: str | None = Field(
2515
+ None,
2516
+ alias='userTimezone',
2517
+ description='IANA time zone name for the executing user (e.g. "America/New_York").',
2518
+ )
2519
+ run_id: str | None = Field(
2520
+ None,
2521
+ alias='runId',
2522
+ description='Optional client-supplied run ID. Idempotency-Key header takes precedence.',
2523
+ )
2524
+ automation_id: str | None = Field(
2525
+ None, alias='automationId', description='Workflow id for usage attribution.'
2526
+ )
2527
+ source: WorkflowActionSource | None = Field(
2528
+ None, description='UI surface that triggered this action.'
2529
+ )
2530
+
2531
+
2532
+ class AccessConfigDto(BaseModel):
2533
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2534
+ visibility: Visibility = Field(
2535
+ ...,
2536
+ description='Visibility tier. `shared` applies the group-permission map; `private` ignores groups and uses owner + sharedWith for access.',
2537
+ examples=['shared'],
2538
+ )
2539
+ group_permissions: dict[str, GroupPermissionDto] = Field(
2540
+ ...,
2541
+ alias='groupPermissions',
2542
+ description='Map of group UUID -> { use, manage } booleans. Empty object when visibility is `private`.',
2543
+ examples=[{'group_eng_uuid': {'use': True, 'manage': False}}],
2544
+ )
2545
+ guardrails: list[str] = Field(
2546
+ ...,
2547
+ description='Free-form guardrail labels enforced at run time (e.g. PII redaction profile names).',
2548
+ examples=[[]],
2549
+ )
2550
+ shared_with: list[SharedUserDto] = Field(
2551
+ ...,
2552
+ alias='sharedWith',
2553
+ description='Per-user share entries used for private-visibility scopes.',
2554
+ examples=[[]],
2555
+ )
2556
+ owner_user_id: str | None = Field(
2557
+ None,
2558
+ alias='ownerUserId',
2559
+ description='Clerk user id of the scope owner. Set on first write; cannot be changed by clients.',
2560
+ examples=['user_2abc'],
2561
+ )
2562
+ owner_email: str | None = Field(
2563
+ None,
2564
+ alias='ownerEmail',
2565
+ description='Lowercased email of the scope owner. Used by private-scope ACL when owner email matches.',
2566
+ examples=['alice@example.com'],
2567
+ )
2568
+
2569
+
2570
+ class AgentDeployResponseDto(BaseModel):
2571
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2572
+ agent: AgentDto = Field(
2573
+ ...,
2574
+ description='The workflow after the deploy. `hasUnpublishedChanges` is false and `activeVariationId` matches the newly-published variation.',
2575
+ )
2576
+ deployed_at: str = Field(
2577
+ ...,
2578
+ alias='deployedAt',
2579
+ description='Server-side timestamp at which the deploy completed.',
2580
+ examples=['2026-05-11T10:00:00.000Z'],
2581
+ )
2582
+
2583
+
2584
+ class AgentSelectionDto(BaseModel):
2585
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2586
+ model: str | None = Field(None, description='Override model name for the orchestration step.')
2587
+ model_settings: ModelSettingsDto | None = Field(
2588
+ None,
2589
+ alias='modelSettings',
2590
+ description='Model-specific runtime controls such as reasoning effort and context window.',
2591
+ )
2592
+ agents: list[AgentSelectionEntryDto] = Field(
2593
+ ..., description='Ordered list of scopes to invoke. Must contain at least one entry.'
2594
+ )
2595
+
2596
+
2597
+ class BatchCreateCustomContextItemsDto(BaseModel):
2598
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2599
+ items: list[CreateCustomContextItemDto] = Field(
2600
+ ...,
2601
+ description='Custom context items to upsert. Batch imports are idempotent by item hierarchy.',
2602
+ )
2603
+
2604
+
2605
+ class ConversationDto(BaseModel):
2606
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2607
+ thread_id: str = Field(
2608
+ ...,
2609
+ alias='threadId',
2610
+ description='Opaque thread/checkpoint id. It is not owned by a single scope; a conversation can span multiple workflows.',
2611
+ examples=['agent_42_abc-xyz'],
2612
+ )
2613
+ skill_id: float | None = Field(
2614
+ ...,
2615
+ alias='skillId',
2616
+ description='Numeric scope id returned by the list/detail adapter. This is not conversation ownership.',
2617
+ examples=[42],
2618
+ )
2619
+ messages: list[ConversationMessageDto] = Field(
2620
+ ..., description='Conversation turns, in chronological order.'
2621
+ )
2622
+ message_window: ConversationMessageWindowDto | None = Field(
2623
+ None,
2624
+ alias='messageWindow',
2625
+ description='Present only when a bounded message window was requested and honored.',
2626
+ )
2627
+ created_at: str = Field(
2628
+ ...,
2629
+ alias='createdAt',
2630
+ description='ISO-8601 timestamp of the first checkpoint for this thread.',
2631
+ examples=['2026-05-01T10:00:00.000Z'],
2632
+ )
2633
+ updated_at: str = Field(
2634
+ ...,
2635
+ alias='updatedAt',
2636
+ description='ISO-8601 timestamp of the latest checkpoint for this thread.',
2637
+ examples=['2026-05-01T11:00:00.000Z'],
2638
+ )
2639
+
2640
+
2641
+ class CreateAgentDto(BaseModel):
2642
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2643
+ name: str | None = Field(
2644
+ ...,
2645
+ description='Display name for the workflow. Will be slugified into a URL-safe path.',
2646
+ examples=['Daily Sales Report'],
2647
+ max_length=200,
2648
+ min_length=1,
2649
+ )
2650
+ type: AgentType | None = Field(
2651
+ ...,
2652
+ description='Workflow type. Only `workflow` is supported; `task` is accepted as a deprecated alias and silently upgraded to `workflow`.',
2653
+ examples=['workflow'],
2654
+ )
2655
+ description: str | None = Field(
2656
+ None,
2657
+ description='Optional one-paragraph description shown in the builder and workflow catalog.',
2658
+ examples=['Generates a daily sales report from CRM data.'],
2659
+ )
2660
+ trigger: TriggerDto | None = Field(
2661
+ None,
2662
+ description='Trigger configuration (schedule / webhook / api / slack / manual). Schedule shape is fully validated; other trigger types are opaque.',
2663
+ )
2664
+ agent_selection: AgentSelectionDto | None = Field(
2665
+ None,
2666
+ alias='agentSelection',
2667
+ description='Workflow selection (for task workflows): ordered scopes plus per-scope instructions.',
2668
+ )
2669
+ workflow_structure: WorkflowStructureDto | None = Field(
2670
+ None,
2671
+ alias='workflowStructure',
2672
+ description='Workflow graph (nodes + edges) when `type` is `workflow`. Unknown node/edge keys and out-of-enum node types are rejected with a 422.',
2673
+ )
2674
+ access_config: AgentAccessConfigDto | None = Field(
2675
+ None,
2676
+ alias='accessConfig',
2677
+ description='Access configuration. Omit to use the default (full-org shared with use + manage).',
2678
+ )
2679
+
2680
+
2681
+ class CreateSkillDto(BaseModel):
2682
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2683
+ name: str | None = Field(
2684
+ ...,
2685
+ description='Display name for the scope. Will be slugified into a URL-safe path.',
2686
+ examples=['Customer Churn Analyzer'],
2687
+ max_length=200,
2688
+ min_length=1,
2689
+ )
2690
+ description: str | None = Field(
2691
+ None,
2692
+ description='Optional one-paragraph description shown in the builder and scope catalog.',
2693
+ examples=['Predicts churn risk for a customer given a 90-day usage window.'],
2694
+ )
2695
+ expected_output: str | None = Field(
2696
+ None,
2697
+ alias='expectedOutput',
2698
+ description='Optional summary of the expected output schema, used when supervising other scopes.',
2699
+ examples=['JSON: { churn_probability: number, drivers: string[] }'],
2700
+ )
2701
+ instructions: list[str] | None = Field(
2702
+ None,
2703
+ description='Ordered list of system-prompt instruction fragments. Joined at run time.',
2704
+ examples=[['You are a senior data analyst.', 'Always cite the SQL you used.']],
2705
+ )
2706
+ toolset: ToolsetDto | None = Field(
2707
+ None,
2708
+ description='Toolset configuration (tools this scope may invoke). Service sanitizes the shape on write.',
2709
+ )
2710
+ model: str | None = Field(
2711
+ None,
2712
+ description='Model identifier to use at run time (e.g. `claude-sonnet-4-5`). Falls back to org default when absent.',
2713
+ examples=['claude-sonnet-4-5'],
2714
+ )
2715
+ model_settings: ModelSettingsDto | None = Field(
2716
+ None,
2717
+ alias='modelSettings',
2718
+ description='Model-specific runtime controls such as reasoning effort and context window.',
2719
+ )
2720
+ connection_set: list[dict[str, Any]] | None = Field(
2721
+ None,
2722
+ alias='connectionSet',
2723
+ description='List of integration connection refs available to this scope. Shape is integration-specific.',
2724
+ examples=[[]],
2725
+ )
2726
+ context_selections: list[dict[str, Any]] | None = Field(
2727
+ None,
2728
+ alias='contextSelections',
2729
+ description='Selected context items (sources / docs) the scope may read.',
2730
+ examples=[[]],
2731
+ )
2732
+ interfaces: list[dict[str, Any]] | None = Field(
2733
+ None,
2734
+ description='Interface configuration (chat, API, webhook…). Shape is interface-specific.',
2735
+ examples=[[]],
2736
+ )
2737
+ access_config: AccessConfigDto | None = Field(
2738
+ None,
2739
+ alias='accessConfig',
2740
+ description='Access configuration. Omit to use the default (full-org shared with use + manage).',
2741
+ )
2742
+
2743
+
2744
+ class EvaluationConfigDto(BaseModel):
2745
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2746
+ enabled: bool = Field(..., description='Whether scheduled evaluations are enabled')
2747
+ cadence: EvaluationCadenceDto | None = Field(None, description='Schedule cadence configuration')
2748
+ judge_model: str | None = Field(
2749
+ None,
2750
+ alias='judgeModel',
2751
+ description='Model ID for the judge LLM',
2752
+ examples=['openai/gpt-4o'],
2753
+ )
2754
+ judge_guidance: str | None = Field(
2755
+ None, alias='judgeGuidance', description='Custom guidance for the judge LLM'
2756
+ )
2757
+ notifications: EvaluationNotificationsDto = Field(
2758
+ ..., description='Regression notification settings'
2759
+ )
2760
+
2761
+
2762
+ class SkillDto(BaseModel):
2763
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2764
+ id: float = Field(
2765
+ ...,
2766
+ description='Numeric scope id (stable per-org; not reused after delete).',
2767
+ examples=[42],
2768
+ )
2769
+ slug: str = Field(
2770
+ ...,
2771
+ description='URL-safe slug used in human-readable links. Unique per org.',
2772
+ examples=['customer-churn-analyzer-a3f'],
2773
+ )
2774
+ name: str | None = Field(
2775
+ ...,
2776
+ description='Display name of the scope. Shown in the builder and in run logs.',
2777
+ examples=['Customer Churn Analyzer'],
2778
+ )
2779
+ description: str | None = Field(
2780
+ None,
2781
+ description='Optional one-paragraph description of what this scope does.',
2782
+ examples=['Predicts churn risk for a customer given a 90-day usage window.'],
2783
+ )
2784
+ status: ResourceLifecycleStatus = Field(
2785
+ ...,
2786
+ description='Lifecycle status. `draft` = never deployed. `active` = deployed. `deleted` = soft-deleted.',
2787
+ examples=['active'],
2788
+ )
2789
+ org_uuid: str = Field(
2790
+ ...,
2791
+ alias='orgUuid',
2792
+ description='Org UUID this scope belongs to. Matches the caller’s principal.',
2793
+ examples=['00000000-0000-0000-0000-000000000001'],
2794
+ )
2795
+ active_variation_id: str | None = Field(
2796
+ None,
2797
+ alias='activeVariationId',
2798
+ description='Active (deployed) variation id. Null until the scope is first deployed.',
2799
+ examples=['00000000-0000-4000-a000-000000000100'],
2800
+ )
2801
+ draft_variation_id: str | None = Field(
2802
+ None,
2803
+ alias='draftVariationId',
2804
+ description='Most recent draft variation id. Null when there is no draft pending.',
2805
+ examples=['00000000-0000-4000-a000-000000000101'],
2806
+ )
2807
+ has_unpublished_changes: bool = Field(
2808
+ ...,
2809
+ alias='hasUnpublishedChanges',
2810
+ description='True when the draft variation differs from the active variation (deploy would publish changes).',
2811
+ examples=[False],
2812
+ )
2813
+ access_config: AccessConfigDto = Field(
2814
+ ...,
2815
+ alias='accessConfig',
2816
+ description='Access configuration — who in the org can use / manage this scope.',
2817
+ )
2818
+ pending_ownership_transfer: (
2819
+ PendingOwnershipTransferDto | None
2820
+ ) = (
2821
+ Field(None, alias='pendingOwnershipTransfer', description='Pending ownership transfer awaiting recipient acceptance. Absent when no request is in flight.')
2822
+ )
2823
+ variation: SkillVariationDto | None = Field(
2824
+ None,
2825
+ description='Variation-detail payload (`toolset`, `instructions`, `model`, etc.) for the requested view. Present on detail responses; absent on list rows.',
2826
+ )
2827
+ created_at: str = Field(
2828
+ ...,
2829
+ alias='createdAt',
2830
+ description='Creation timestamp.',
2831
+ examples=['2026-05-01T10:00:00.000Z'],
2832
+ )
2833
+ updated_at: str = Field(
2834
+ ...,
2835
+ alias='updatedAt',
2836
+ description='Most recent update timestamp.',
2837
+ examples=['2026-05-11T10:00:00.000Z'],
2838
+ )
2839
+ deleted_at: str | None = Field(
2840
+ None,
2841
+ alias='deletedAt',
2842
+ description='Soft-delete timestamp. Null for active scopes.',
2843
+ examples=[None],
2844
+ )
2845
+ can_manage: bool = Field(
2846
+ ...,
2847
+ alias='canManage',
2848
+ description='Whether the requesting principal can manage (edit/delete/deploy) this scope. Derived server-side from the principal + accessConfig. Present on every Scope response.',
2849
+ examples=[True],
2850
+ )
2851
+ can_use: bool = Field(
2852
+ ...,
2853
+ alias='canUse',
2854
+ description='Whether the requesting principal can use (run, view history of) this scope. Derived server-side from the principal + accessConfig.',
2855
+ examples=[True],
2856
+ )
2857
+ manage_denial: ManageDenial | None = Field(
2858
+ ...,
2859
+ alias='manageDenial',
2860
+ description='Why `canManage` is false, for client-facing guidance: `needs_group_manage` (shared, but no group you belong to grants Manage) or `not_owner` (private, and you are not the owner). `null` when `canManage` is true.',
2861
+ examples=['needs_group_manage'],
2862
+ )
2863
+
2864
+
2865
+ class UpdateAgentDto(BaseModel):
2866
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2867
+ name: str | None = Field(
2868
+ None,
2869
+ description='New display name for the workflow.',
2870
+ examples=['Daily Sales Report v2'],
2871
+ max_length=200,
2872
+ min_length=1,
2873
+ )
2874
+ type: AgentType | None = Field(
2875
+ None, description='Updated workflow type. Rarely changed after creation.', examples=['task']
2876
+ )
2877
+ description: str | None = Field(
2878
+ None,
2879
+ description='Updated description.',
2880
+ examples=['Generates a daily sales report broken down by region.'],
2881
+ )
2882
+ trigger: TriggerDto | None = Field(
2883
+ None,
2884
+ description='Updated trigger configuration. Schedule shape is fully validated; other trigger types are opaque.',
2885
+ )
2886
+ agent_selection: AgentSelectionDto | None = Field(
2887
+ None, alias='agentSelection', description='Updated workflow selection.'
2888
+ )
2889
+ workflow_structure: WorkflowStructureDto | None = Field(
2890
+ None,
2891
+ alias='workflowStructure',
2892
+ description='Updated workflow graph (nodes + edges). Unknown node/edge keys and out-of-enum node types are rejected with a 422.',
2893
+ )
2894
+ access_config: AgentAccessConfigDto | None = Field(
2895
+ None,
2896
+ alias='accessConfig',
2897
+ description='Updated access configuration. The service rejects changes that would lock the caller out of use + manage.',
2898
+ )
2899
+
2900
+
2901
+ class UpdateSkillDto(BaseModel):
2902
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2903
+ name: str | None = Field(
2904
+ None,
2905
+ description='New display name for the scope.',
2906
+ examples=['Customer Churn Analyzer v2'],
2907
+ max_length=200,
2908
+ min_length=1,
2909
+ )
2910
+ description: str | None = Field(
2911
+ None,
2912
+ description='Updated description.',
2913
+ examples=['Predicts churn risk over a 180-day window.'],
2914
+ )
2915
+ expected_output: str | None = Field(
2916
+ None,
2917
+ alias='expectedOutput',
2918
+ description='Updated expected-output summary, used when this scope is supervised.',
2919
+ examples=['JSON: { churn_probability: number }'],
2920
+ )
2921
+ instructions: list[str] | None = Field(
2922
+ None,
2923
+ description='Updated instruction fragments. Replaces the prior list when present.',
2924
+ examples=[['You are a senior data analyst.']],
2925
+ )
2926
+ toolset: ToolsetDto | None = Field(None, description='Updated toolset configuration.')
2927
+ model: str | None = Field(
2928
+ None,
2929
+ description='Updated model id. Pass `null` (explicit) to clear and use the org default.',
2930
+ examples=['claude-sonnet-4-5'],
2931
+ )
2932
+ model_settings: ModelSettingsDto | None = Field(
2933
+ None,
2934
+ alias='modelSettings',
2935
+ description='Updated model-specific runtime controls. Pass `null` to clear.',
2936
+ )
2937
+ connection_set: list[dict[str, Any]] | None = Field(
2938
+ None,
2939
+ alias='connectionSet',
2940
+ description='Updated connection set. Shape is integration-specific.',
2941
+ examples=[[]],
2942
+ )
2943
+ context_selections: list[dict[str, Any]] | None = Field(
2944
+ None,
2945
+ alias='contextSelections',
2946
+ description='Updated context selections (sources / docs the scope may read).',
2947
+ examples=[[]],
2948
+ )
2949
+ interfaces: list[dict[str, Any]] | None = Field(
2950
+ None, description='Updated interface configuration.', examples=[[]]
2951
+ )
2952
+ evaluations: list[dict[str, Any]] | None = Field(
2953
+ None,
2954
+ description='Updated evaluation entries (task + expected-output pairs) saved for the draft variation. Replaces the prior list when present.',
2955
+ examples=[[]],
2956
+ )
2957
+ supervision_subordinate_descriptions: dict[str, str] | None = Field(
2958
+ None,
2959
+ alias='supervisionSubordinateDescriptions',
2960
+ description='Map of subordinate scope id (stringified) to the manager-provided description blurb. Replaces the prior map when present.',
2961
+ examples=[{'12': 'Reads warehouse facts', '17': 'Drafts the report'}],
2962
+ )
2963
+ access_config: AccessConfigDto | None = Field(
2964
+ None,
2965
+ alias='accessConfig',
2966
+ description='Updated access configuration. The service rejects changes that would lock the caller out of use + manage.',
2967
+ )
2968
+ manager_id: float | None = Field(
2969
+ None,
2970
+ alias='managerId',
2971
+ description='Re-parent the scope under a new manager (or remove its current manager when null). When this field is present, all other fields are ignored.',
2972
+ examples=[17],
2973
+ )
2974
+
2975
+
2976
+ class RunConfigDto(BaseModel):
2977
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
2978
+ model: str | None = Field(None, description='Model id, e.g. anthropic/claude-sonnet-4.6.')
2979
+ model_settings: RunModelSettingsDto | None = Field(
2980
+ None, alias='modelSettings', description='Model-specific runtime controls.'
2981
+ )
2982
+ context_selections: list[dict[str, Any]] | None = Field(
2983
+ None, alias='contextSelections', description='Context selections (runtime-owned shape).'
2984
+ )
2985
+ connection_selections: list[dict[str, Any]] | None = Field(
2986
+ None,
2987
+ alias='connectionSelections',
2988
+ description='Database connection selections (runtime-owned shape).',
2989
+ )
2990
+ connection_set: list[dict[str, Any]] | None = Field(
2991
+ None, alias='connectionSet', description='Schema scopes (runtime-owned shape).'
2992
+ )
2993
+ connection_all_mode_ids: list[str] | None = Field(None, alias='connectionAllModeIds')
2994
+ guardrails: list[str] | None = Field(None, description='Guardrail ids applied to the run.')
2995
+ toolset: dict[str, Any] | None = Field(None, description='Map of tool name to tool config.')
2996
+ strategies: list[str] | None = None
2997
+ experimental_features: bool | None = Field(None, alias='experimentalFeatures')
2998
+ debug: bool | None = None
2999
+ composer_file_offload: bool | None = Field(
3000
+ None, alias='composerFileOffload', description='Set false to keep composer output inline.'
3001
+ )
3002
+
3003
+
3004
+ class SkillRunDto(BaseModel):
3005
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
3006
+ message: str = Field(..., description='The user message to send.')
3007
+ session_id: str = Field(
3008
+ ...,
3009
+ alias='sessionId',
3010
+ description='Opaque client-generated conversation token for continuity. The server NEVER derives the run target identity (scope/workflow/modus) from this string — target identity comes only from the request path and DTO (see RunTarget). It is used solely to thread successive turns of the same conversation together.',
3011
+ )
3012
+ organization_id: str | None = Field(
3013
+ None,
3014
+ alias='organizationId',
3015
+ description="Organization id. Ignored for authenticated callers — the server uses the principal's org.",
3016
+ )
3017
+ version: Version | None = Field(
3018
+ None, description='Saved version to run (scope/workflow; ignored for Modus).'
3019
+ )
3020
+ file_thread_id: str | None = Field(
3021
+ None, alias='fileThreadId', description='Document-scoped conversation thread id.'
3022
+ )
3023
+ config: RunConfigDto | None = None
3024
+ attachments: AttachmentsDto | None = None
3025
+ user_context: UserContextDto | None = Field(None, alias='userContext')
3026
+ supplemental_context: SupplementalContextDto | None = Field(None, alias='supplementalContext')
3027
+ source: RunSource | None = Field(None, description='Origin of the run.')
3028
+ run_id: str | None = Field(
3029
+ None, alias='runId', description='Client-supplied run id (Idempotency-Key header wins).'
3030
+ )
3031
+ stream_protocol_version: StreamProtocolVersion | None = Field(
3032
+ None,
3033
+ alias='streamProtocolVersion',
3034
+ description='Streaming protocol version. Version 2 supports assistant-content replacement events.',
3035
+ )
3036
+ experimental_features: bool | None = Field(None, alias='experimentalFeatures')
3037
+ debug: bool | None = None
3038
+ subordinate_skill_ids: list[float] | None = Field(
3039
+ None,
3040
+ alias='subordinateSkillIds',
3041
+ description='Subordinate scope ids for an unsaved supervisor-scope draft test.',
3042
+ )
3043
+
3044
+
3045
+ class DeployResponseDto(BaseModel):
3046
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
3047
+ skill: SkillDto = Field(
3048
+ ...,
3049
+ description='The scope after the deploy. `hasUnpublishedChanges` is false and `activeVariationId` matches the newly-published variation.',
3050
+ )
3051
+ deployed_at: str = Field(
3052
+ ...,
3053
+ alias='deployedAt',
3054
+ description='Server-side timestamp at which the deploy completed.',
3055
+ examples=['2026-05-11T10:00:00.000Z'],
3056
+ )
3057
+
3058
+
3059
+ class ListSkillsResponseDto(BaseModel):
3060
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
3061
+ skills: list[SkillDto] = Field(
3062
+ ...,
3063
+ description='Page of scopes the caller can at least `use`. Scopes the caller cannot see are filtered out (not enumerated).',
3064
+ )
3065
+ next_page_token: str | None = Field(
3066
+ ...,
3067
+ alias='nextPageToken',
3068
+ description='Opaque token for the next page; `null` when this was the last page. Pass as `pageToken` on the next request.',
3069
+ examples=['eyJsYXN0SWQiOjQyfQ'],
3070
+ )
3071
+
3072
+
3073
+ class AgentRunDto(BaseModel):
3074
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
3075
+ message: str = Field(..., description='The user message to send.')
3076
+ session_id: str = Field(
3077
+ ...,
3078
+ alias='sessionId',
3079
+ description='Opaque client-generated conversation token for continuity. The server NEVER derives the run target identity (scope/workflow/modus) from this string — target identity comes only from the request path and DTO (see RunTarget). It is used solely to thread successive turns of the same conversation together.',
3080
+ )
3081
+ organization_id: str | None = Field(
3082
+ None,
3083
+ alias='organizationId',
3084
+ description="Organization id. Ignored for authenticated callers — the server uses the principal's org.",
3085
+ )
3086
+ version: Version | None = Field(
3087
+ None, description='Saved version to run (scope/workflow; ignored for Modus).'
3088
+ )
3089
+ file_thread_id: str | None = Field(
3090
+ None, alias='fileThreadId', description='Document-scoped conversation thread id.'
3091
+ )
3092
+ config: RunConfigDto | None = None
3093
+ attachments: AttachmentsDto | None = None
3094
+ user_context: UserContextDto | None = Field(None, alias='userContext')
3095
+ supplemental_context: SupplementalContextDto | None = Field(None, alias='supplementalContext')
3096
+ source: RunSource | None = Field(None, description='Origin of the run.')
3097
+ run_id: str | None = Field(
3098
+ None, alias='runId', description='Client-supplied run id (Idempotency-Key header wins).'
3099
+ )
3100
+ stream_protocol_version: StreamProtocolVersion | None = Field(
3101
+ None,
3102
+ alias='streamProtocolVersion',
3103
+ description='Streaming protocol version. Version 2 supports assistant-content replacement events.',
3104
+ )
3105
+ experimental_features: bool | None = Field(None, alias='experimentalFeatures')
3106
+ debug: bool | None = None
3107
+
3108
+
3109
+ class ModusRunDto(BaseModel):
3110
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
3111
+ message: str = Field(..., description='The user message to send.')
3112
+ session_id: str = Field(
3113
+ ...,
3114
+ alias='sessionId',
3115
+ description='Opaque client-generated conversation token for continuity. The server NEVER derives the run target identity (scope/workflow/modus) from this string — target identity comes only from the request path and DTO (see RunTarget). It is used solely to thread successive turns of the same conversation together.',
3116
+ )
3117
+ organization_id: str | None = Field(
3118
+ None,
3119
+ alias='organizationId',
3120
+ description="Organization id. Ignored for authenticated callers — the server uses the principal's org.",
3121
+ )
3122
+ version: Version | None = Field(
3123
+ None, description='Saved version to run (scope/workflow; ignored for Modus).'
3124
+ )
3125
+ file_thread_id: str | None = Field(
3126
+ None, alias='fileThreadId', description='Document-scoped conversation thread id.'
3127
+ )
3128
+ config: RunConfigDto | None = None
3129
+ attachments: AttachmentsDto | None = None
3130
+ user_context: UserContextDto | None = Field(None, alias='userContext')
3131
+ supplemental_context: SupplementalContextDto | None = Field(None, alias='supplementalContext')
3132
+ source: RunSource | None = Field(None, description='Origin of the run.')
3133
+ run_id: str | None = Field(
3134
+ None, alias='runId', description='Client-supplied run id (Idempotency-Key header wins).'
3135
+ )
3136
+ stream_protocol_version: StreamProtocolVersion | None = Field(
3137
+ None,
3138
+ alias='streamProtocolVersion',
3139
+ description='Streaming protocol version. Version 2 supports assistant-content replacement events.',
3140
+ )
3141
+ experimental_features: bool | None = Field(None, alias='experimentalFeatures')
3142
+ debug: bool | None = None
3143
+ subordinate_skill_ids: list[float] | None = Field(
3144
+ None, alias='subordinateSkillIds', description='Saved scope ids to scope the Modus run to.'
3145
+ )
3146
+
3147
+
3148
+ class ResumeRunDto(BaseModel):
3149
+ model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel, extra="ignore")
3150
+ message: str = Field(..., description='The user message to send.')
3151
+ session_id: str = Field(
3152
+ ...,
3153
+ alias='sessionId',
3154
+ description='Opaque client-generated conversation token for continuity. The server NEVER derives the run target identity (scope/workflow/modus) from this string — target identity comes only from the request path and DTO (see RunTarget). It is used solely to thread successive turns of the same conversation together.',
3155
+ )
3156
+ organization_id: str | None = Field(
3157
+ None,
3158
+ alias='organizationId',
3159
+ description="Organization id. Ignored for authenticated callers — the server uses the principal's org.",
3160
+ )
3161
+ version: Version | None = Field(
3162
+ None, description='Saved version to run (scope/workflow; ignored for Modus).'
3163
+ )
3164
+ file_thread_id: str | None = Field(
3165
+ None, alias='fileThreadId', description='Document-scoped conversation thread id.'
3166
+ )
3167
+ config: RunConfigDto | None = None
3168
+ attachments: AttachmentsDto | None = None
3169
+ user_context: UserContextDto | None = Field(None, alias='userContext')
3170
+ supplemental_context: SupplementalContextDto | None = Field(None, alias='supplementalContext')
3171
+ source: RunSource | None = Field(None, description='Origin of the run.')
3172
+ run_id: str | None = Field(
3173
+ None, alias='runId', description='Client-supplied run id (Idempotency-Key header wins).'
3174
+ )
3175
+ stream_protocol_version: StreamProtocolVersion | None = Field(
3176
+ None,
3177
+ alias='streamProtocolVersion',
3178
+ description='Streaming protocol version. Version 2 supports assistant-content replacement events.',
3179
+ )
3180
+ experimental_features: bool | None = Field(None, alias='experimentalFeatures')
3181
+ debug: bool | None = None
3182
+ decision: Decision = Field(..., description='Decision that resumes the interrupted run.')