From c7ce3b7747eba8fffc9f4e7ff3092fc0350bf8c4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 24 Sep 2026 01:47:51 +0000 Subject: [PATCH] chore(sdk): regenerate from archastro-openapi@main (generator 0.11.9) --- specs/platform-openapi.json | 7600 ++++++++++++++++- .../platform/channels/api_chat_channel.py | 49 +- src/archastro/platform/client.py | 6 +- src/archastro/platform/types/ai.py | 83 +- src/archastro/platform/types/common.py | 10 +- src/archastro/platform/types/teams.py | 16 +- src/archastro/platform/types/threads.py | 8 +- src/archastro/platform/v1/__init__.py | 6 +- .../platform/v1/resources/__init__.py | 2 +- src/archastro/platform/v1/resources/agents.py | 10 +- src/archastro/platform/v1/resources/ai.py | 232 +- .../platform/v1/resources/artifacts.py | 6 +- .../platform/v1/resources/custom_objects.py | 12 +- src/archastro/platform/v1/resources/files.py | 16 +- src/archastro/platform/v1/resources/orgs.py | 1661 +++- src/archastro/platform/v1/resources/tasks.py | 48 +- src/archastro/platform/v1/resources/teams.py | 62 +- .../platform/v1/resources/threads.py | 14 +- src/archastro/platform/v1/resources/users.py | 24 +- .../channels/test_api_chat_channel.py | 37 +- tests/contract/v1/test_ai.py | 382 +- tests/contract/v1/test_config.py | 27 +- tests/contract/v1/test_custom_objects.py | 23 +- tests/contract/v1/test_orgs.py | 258 +- tests/contract/v1/test_teams.py | 86 +- 25 files changed, 10176 insertions(+), 502 deletions(-) diff --git a/specs/platform-openapi.json b/specs/platform-openapi.json index a888e59..454777a 100644 --- a/specs/platform-openapi.json +++ b/specs/platform-openapi.json @@ -276,6 +276,212 @@ ], "type": "object" }, + "AIEvaluationAnswer": { + "description": "One typed evaluation answer. `type` selects boolean, choice, or score.\n`id` matches the question id.\n", + "discriminator": { + "mapping": { + "boolean": "#/components/schemas/AIEvaluationAnswerBoolean", + "choice": "#/components/schemas/AIEvaluationAnswerChoice", + "score": "#/components/schemas/AIEvaluationAnswerScore" + }, + "propertyName": "type" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/AIEvaluationAnswerBoolean" + }, + { + "$ref": "#/components/schemas/AIEvaluationAnswerChoice" + }, + { + "$ref": "#/components/schemas/AIEvaluationAnswerScore" + } + ] + }, + "AIEvaluationAnswerBoolean": { + "description": "Probability that the statement is true, in `[0, 1]`.", + "example": { + "id": "urgent", + "probability": 1.0, + "type": "boolean" + }, + "properties": { + "id": { + "example": "urgent", + "type": "string" + }, + "probability": { + "example": 1.0, + "type": "number" + }, + "type": { + "default": "boolean", + "enum": [ + "boolean" + ], + "example": "boolean", + "type": "string" + } + }, + "required": [ + "id", + "type", + "probability" + ], + "type": "object" + }, + "AIEvaluationAnswerChoice": { + "description": "Selected option plus the full probability distribution.", + "example": { + "choice": "string", + "confidence": 1.0, + "id": "department", + "probabilities": {}, + "type": "choice" + }, + "properties": { + "choice": { + "example": "string", + "type": "string" + }, + "confidence": { + "example": 1.0, + "type": "number" + }, + "id": { + "example": "department", + "type": "string" + }, + "probabilities": { + "example": {}, + "type": "object" + }, + "type": { + "default": "choice", + "enum": [ + "choice" + ], + "example": "choice", + "type": "string" + } + }, + "required": [ + "id", + "type", + "choice", + "probabilities" + ], + "type": "object" + }, + "AIEvaluationAnswerScore": { + "description": "Probability-weighted position along the caller-defined levels.", + "example": { + "confidence": 1.0, + "id": "frustration", + "legend": {}, + "probabilities": {}, + "score": 1.0, + "type": "score" + }, + "properties": { + "confidence": { + "example": 1.0, + "type": "number" + }, + "id": { + "example": "frustration", + "type": "string" + }, + "legend": { + "example": {}, + "type": "object" + }, + "probabilities": { + "example": {}, + "type": "object" + }, + "score": { + "example": 1.0, + "type": "number" + }, + "type": { + "default": "score", + "enum": [ + "score" + ], + "example": "score", + "type": "string" + } + }, + "required": [ + "id", + "type", + "score", + "legend", + "probabilities" + ], + "type": "object" + }, + "AIEvaluationResult": { + "description": "Result of an evaluation request: typed answers, the model that ran, and\ntoken usage.\n", + "example": { + "answers": [], + "model": "jev-1.13.0", + "session_id": "string", + "usage": { + "input_tokens": 1, + "output_tokens": 1 + } + }, + "properties": { + "answers": { + "description": "Typed answers. Each value is a boolean, choice, or score object with the question `id`.", + "items": { + "$ref": "#/components/schemas/AIEvaluationAnswer" + }, + "type": "array" + }, + "model": { + "description": "Model identifier that produced the answers.", + "example": "jev-1.13.0", + "type": "string" + }, + "session_id": { + "description": "UUID grouping this evaluation's usage record. Generated when omitted on the request.", + "example": "string", + "type": "string" + }, + "usage": { + "$ref": "#/components/schemas/AIEvaluationUsage", + "description": "Token usage for this request. `null` when usage data is unavailable." + } + }, + "required": [ + "model", + "answers" + ], + "type": "object" + }, + "AIEvaluationUsage": { + "description": "Token counts for one evaluation request.", + "example": { + "input_tokens": 1, + "output_tokens": 1 + }, + "properties": { + "input_tokens": { + "description": "Provider-reported input tokens. `null` when the provider omitted the count.", + "example": 1, + "type": "integer" + }, + "output_tokens": { + "description": "Provider-reported output tokens. `null` when the provider omitted the count.", + "example": 1, + "type": "integer" + } + }, + "type": "object" + }, "AIImageResult": { "description": "The result returned by an AI image generation or editing operation. Contains the generated image (as inline data or a URL) along with dimension, size, and usage metadata.", "example": { @@ -6648,6 +6854,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -6746,6 +6953,12 @@ "nullable": true, "type": "integer" }, + "key": { + "description": "For `structured_data` type, what the data is about as set by the sender (for example `\"pr:14963\"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.", + "example": "string", + "nullable": true, + "type": "string" + }, "media_type": { "description": "The media category, e.g. `\"video\"` or `\"audio\"`. Present on `media` type only; omitted otherwise.", "example": "application/json", @@ -6758,7 +6971,7 @@ "type": "string" }, "object": { - "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types.", + "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types.", "example": {}, "type": "object" }, @@ -6769,7 +6982,7 @@ "type": "string" }, "type": { - "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, or `\"chart\"`. Determines which additional fields are present.", + "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, `\"chart\"`, or `\"structured_data\"`. Determines which additional fields are present.", "example": "file", "type": "string" }, @@ -7745,6 +7958,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -7955,6 +8169,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -8405,6 +8620,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -9221,6 +9437,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -9431,6 +9648,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -10287,6 +10505,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -10450,6 +10669,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -11016,6 +11236,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -11226,6 +11447,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -15237,6 +15459,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -15372,6 +15595,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -15698,6 +15922,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -16544,6 +16769,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -21411,6 +21637,30 @@ ], "type": "object" }, + "TeamDeleteImpactResponse": { + "description": "The stored custom-object rows that a Team deletion will physically remove.", + "example": { + "custom_object_count": 1, + "custom_objects_physically_deleted": true + }, + "properties": { + "custom_object_count": { + "description": "All custom-object rows owned by the Team, including soft-deleted rows.", + "example": 1, + "type": "integer" + }, + "custom_objects_physically_deleted": { + "description": "Whether Team deletion physically deletes these rows; no restore is provided.", + "example": true, + "type": "boolean" + } + }, + "required": [ + "custom_object_count", + "custom_objects_physically_deleted" + ], + "type": "object" + }, "TeamInvite": { "description": "A team invite containing a short alphanumeric code that other users can present to join the team.", "example": { @@ -22343,6 +22593,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -22867,7 +23118,7 @@ "type": "string" }, "kind": { - "description": "Thread subtype: `\"standard\"` for ordinary threads, `\"personal\"` for a user-and-owned-agents roster, `\"slack_mirror\"` for the membership-strict mirror of a Slack channel, or `\"slashwork_mirror\"` for the membership-strict mirror of a Slashwork group. `personal` is an explicit user-thread creation option; mirror kinds are server-derived.", + "description": "Thread subtype: `\"standard\"` for ordinary threads, `\"personal\"` for a user-and-owned-agents roster, `\"feed\"` for a post feed with inline replies, `\"slack_mirror\"` for the membership-strict mirror of a Slack channel, or `\"slashwork_mirror\"` for the membership-strict mirror of a Slashwork group. `personal` and `feed` are explicit creation options; mirror kinds are server-derived.", "example": "string", "nullable": true, "type": "string" @@ -22982,6 +23233,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -23177,11 +23429,12 @@ "type": "string" }, "visibility": { - "description": "Who can read the thread: `team` for every owning-team member, `restricted` for team-readable threads with an explicit roster, or `private` for roster-only access.", + "description": "Who can read the thread: `team` for every owning-team member, `restricted` for team-readable threads with an explicit roster, `private` for roster-only access, or `org` for every member of the owning organization.", "enum": [ "team", "restricted", - "private" + "private", + "org" ], "example": "team", "type": "string" @@ -23247,6 +23500,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -33981,9 +34235,10 @@ "type": "string" }, "kind": { - "description": "Optional behavioral subtype. `personal` is accepted only for a user-owned thread and limits membership to that user and agents currently owned by them. Mirror kinds remain server-derived and cannot be selected by callers.", + "description": "Optional behavioral subtype. `personal` is accepted only for a user-owned thread and limits membership to that user and agents currently owned by them. `feed` is accepted for any owner and renders the thread as a post feed: message lists return top-level posts with their newest replies inline, and agent responses attach to the root post. Mirror kinds remain server-derived and cannot be selected by callers.", "enum": [ - "personal" + "personal", + "feed" ], "example": "personal", "type": "string" @@ -34095,11 +34350,12 @@ "type": "string" }, "visibility": { - "description": "Thread visibility. A team-owned thread with members must explicitly use `restricted` or `private`. User- and agent-owned threads with members default to `private` and reject every other value.", + "description": "Thread visibility. A team-owned thread with members must explicitly use `restricted` or `private`. User- and agent-owned threads with members default to `private` and reject every other value. `org` is only valid on an organization-owned thread with no team, user, or agent owner.", "enum": [ "team", "restricted", - "private" + "private", + "org" ], "example": "team", "type": "string" @@ -34473,6 +34729,7 @@ "application/json": { "schema": { "example": { + "attribution": {}, "context": {}, "messages": [ { @@ -34522,6 +34779,11 @@ "session_id": "string" }, "properties": { + "attribution": { + "description": "Optional caller tags recorded on the LLM-call accounting row. Allowed keys: `task_id` (max 64 chars), `work_id` (max 64), `agent_kind` (one of `worker`, `one_off`, `subagent`, `overseer`, `task_reviewer`, `interactive`, `daemon_job`), `agent_id` (max 64), `client` (max 32). Anything else is a 400.", + "example": {}, + "type": "object" + }, "context": { "description": "Key-value map used to resolve template variables in message content. Omit if messages contain no templates.", "example": {}, @@ -34876,6 +35138,9 @@ "402": { "description": "Payment required — plan does not allow this feature" }, + "403": { + "description": "Forbidden — invalid billing session token" + }, "422": { "description": "Validation failed" } @@ -34897,6 +35162,7 @@ "application/json": { "schema": { "example": { + "attribution": {}, "context": {}, "messages": [ { @@ -34945,6 +35211,11 @@ "session_id": "string" }, "properties": { + "attribution": { + "description": "Optional caller tags recorded on the LLM-call accounting row. Allowed keys: `task_id` (max 64 chars), `work_id` (max 64), `agent_kind` (one of `worker`, `one_off`, `subagent`, `overseer`, `task_reviewer`, `interactive`, `daemon_job`), `agent_id` (max 64), `client` (max 32). Anything else is a 400.", + "example": {}, + "type": "object" + }, "context": { "description": "Key-value map used to resolve template variables in message content. Omit if messages contain no templates.", "example": {}, @@ -35314,6 +35585,9 @@ }, "402": { "description": "Payment required — plan does not allow this feature" + }, + "403": { + "description": "Forbidden — invalid billing session token" } }, "summary": "Stream a chat completion", @@ -35418,7 +35692,7 @@ }, "properties": { "capabilities": { - "description": "Machine-readable model capabilities. `\"image\"` marks image-input chat, `\"search\"` marks built-in web search, and `\"thinking\"` marks models with configurable reasoning. Empty when the catalog entry declares no special capabilities.", + "description": "Machine-readable model capabilities. `\"image\"` marks image-input chat, `\"search\"` marks built-in web search, `\"temperature\"` marks models that accept the temperature generation parameter, and `\"thinking\"` marks models with configurable reasoning. Empty when the catalog entry declares no special capabilities.", "example": [ "image" ], @@ -35426,6 +35700,7 @@ "enum": [ "image", "search", + "temperature", "thinking" ], "type": "string" @@ -35597,6 +35872,401 @@ ] } }, + "/api/v1/ai/evaluation/evaluations": { + "post": { + "description": "Sends a shared `state` and a list of typed questions to an evaluation\nmodel and returns typed answers. This is not chat completion and not\nJSON-schema structured output: there is no generated text.\n\nEach question is a `boolean`, `choice`, or `score` object with its own\n`id`. Answers come back as the same three typed objects, each carrying\nthat `id`.\n\nThe authenticated app must have the `llm_calls` entitlement enabled on its\nplan. Requests that exceed the plan quota are rejected with `402`. Token\nusage is recorded against the authenticated app and organization.\n", + "operationId": "post_api_v1_ai_evaluation_evaluations", + "parameters": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "example": { + "model": "string", + "questions": [], + "session_id": "string" + }, + "properties": { + "model": { + "description": "Evaluation model identifier. Omit to use the platform default.", + "example": "string", + "type": "string" + }, + "questions": { + "description": "Nonempty list of boolean, choice, or score questions. Each question must include `id`, `type`, and `instructions`.", + "example": [], + "items": { + "description": "One evaluation question. Public types are `boolean`, `choice`, and `score`,\nselected by `type`. Each question carries its own `id`.\n", + "discriminator": { + "propertyName": "type" + }, + "oneOf": [ + { + "description": "True/false criterion. TypeSafe writes this as `noul`.", + "example": { + "criteria": { + "false_description": "An example description.", + "true_description": "An example description." + }, + "id": "urgent", + "instructions": "string", + "type": "boolean" + }, + "properties": { + "criteria": { + "description": "Optional true/false descriptions.", + "example": { + "false_description": "An example description.", + "true_description": "An example description." + }, + "properties": { + "false_description": { + "description": "What counts as false.", + "example": "An example description.", + "type": "string" + }, + "true_description": { + "description": "What counts as true.", + "example": "An example description.", + "type": "string" + } + }, + "type": "object" + }, + "id": { + "description": "Caller-chosen question id. The matching answer carries this same `id`.", + "example": "urgent", + "type": "string" + }, + "instructions": { + "description": "What to judge.", + "example": "string", + "type": "string" + }, + "type": { + "default": "boolean", + "enum": [ + "boolean" + ], + "example": "boolean", + "type": "string" + } + }, + "required": [ + "id", + "type", + "instructions" + ], + "type": "object" + }, + { + "description": "Pick one named option from `criteria`.", + "example": { + "criteria": {}, + "id": "department", + "instructions": "string", + "type": "choice" + }, + "properties": { + "criteria": { + "description": "Nonempty map of option id to description.", + "example": {}, + "type": "object" + }, + "id": { + "description": "Caller-chosen question id. The matching answer carries this same `id`.", + "example": "department", + "type": "string" + }, + "instructions": { + "description": "What to judge.", + "example": "string", + "type": "string" + }, + "type": { + "default": "choice", + "enum": [ + "choice" + ], + "example": "choice", + "type": "string" + } + }, + "required": [ + "id", + "type", + "instructions", + "criteria" + ], + "type": "object" + }, + { + "description": "Place the state along ordered `criteria` levels.", + "example": { + "criteria": [ + "string" + ], + "id": "frustration", + "instructions": "string", + "type": "score" + }, + "properties": { + "criteria": { + "description": "At least two ordered level descriptions.", + "example": [ + "string" + ], + "items": { + "type": "string" + }, + "type": "array" + }, + "id": { + "description": "Caller-chosen question id. The matching answer carries this same `id`.", + "example": "frustration", + "type": "string" + }, + "instructions": { + "description": "What to judge.", + "example": "string", + "type": "string" + }, + "type": { + "default": "score", + "enum": [ + "score" + ], + "example": "score", + "type": "string" + } + }, + "required": [ + "id", + "type", + "instructions", + "criteria" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "session_id": { + "description": "Optional UUID grouping this evaluation under one session in the Developers dashboard. Generated when omitted.", + "example": "string", + "type": "string" + }, + "state": { + "description": "Shared content the model judges. A string, JSON object, or JSON array. Every question in the request sees this same state." + } + }, + "required": [ + "state", + "questions" + ], + "type": "object" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AIEvaluationResult" + } + } + }, + "description": "Typed answers as a list of boolean, choice, or score objects, plus model and usage." + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "402": { + "description": "Payment required — plan does not allow this feature" + }, + "403": { + "description": "Forbidden — app scope required" + }, + "422": { + "description": "Evaluation failed" + } + }, + "summary": "Create an evaluation", + "x-auth": [ + "publishable_key", + "bearer" + ] + } + }, + "/api/v1/ai/evaluation/models": { + "get": { + "description": "Returns the set of evaluation models that can be used with the evaluations\nendpoint. The list reflects models currently enabled for the platform and\nincludes each model's identifier and whether it is the default.\n\nUse the `id` field from any entry in `data` as the `model` value when\ncalling the evaluations endpoint.\n", + "operationId": "get_api_v1_ai_evaluation_models", + "parameters": [], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "description": "The set of AI models available for evaluation.", + "example": { + "data": [ + { + "capabilities": [ + "image" + ], + "context_window": 200000, + "default": true, + "id": "claude-sonnet-4-6", + "input_media_formats": [ + "string" + ], + "name": "Example Name", + "output_media_formats": [ + "string" + ] + } + ] + }, + "properties": { + "data": { + "description": "Array of available evaluation model objects. At least one entry is always present.", + "example": [ + { + "capabilities": [ + "image" + ], + "context_window": 200000, + "default": true, + "id": "claude-sonnet-4-6", + "input_media_formats": [ + "string" + ], + "name": "Example Name", + "output_media_formats": [ + "string" + ] + } + ], + "items": { + "description": "An AI model available on the platform. Returned in model-listing responses so clients can populate model pickers and resolve the platform default.", + "example": { + "capabilities": [ + "image" + ], + "context_window": 200000, + "default": true, + "id": "claude-sonnet-4-6", + "input_media_formats": [ + "string" + ], + "name": "Example Name", + "output_media_formats": [ + "string" + ] + }, + "properties": { + "capabilities": { + "description": "Machine-readable model capabilities. `\"image\"` marks image-input chat, `\"search\"` marks built-in web search, `\"temperature\"` marks models that accept the temperature generation parameter, and `\"thinking\"` marks models with configurable reasoning. Empty when the catalog entry declares no special capabilities.", + "example": [ + "image" + ], + "items": { + "enum": [ + "image", + "search", + "temperature", + "thinking" + ], + "type": "string" + }, + "type": "array" + }, + "context_window": { + "description": "Maximum context-window size in tokens this model accepts, when the platform publishes it. Use it to size prompt/history against the real window rather than a hardcoded default. `null` for entries whose window the platform does not report (e.g. legacy or mock model listings); clients should apply a conservative fallback in that case.", + "example": 200000, + "nullable": true, + "type": "integer" + }, + "default": { + "description": "`true` for the model the platform selects when an agent has no `default_model` configured, or for the system-wide fallback in image-generation contexts. Exactly one entry in any given model list carries this flag.", + "example": true, + "type": "boolean" + }, + "id": { + "description": "Provider-assigned model identifier used when specifying a model on API requests, e.g. `\"claude-sonnet-4-6\"` or `\"gemini-2.5-flash\"`.", + "example": "claude-sonnet-4-6", + "type": "string" + }, + "input_media_formats": { + "description": "MIME types accepted in chat `content_parts` image/file inputs for this model. For image-capable chat models this includes values such as `\"image/png\"`. Empty for text-only models.", + "example": [ + "string" + ], + "items": { + "type": "string" + }, + "type": "array" + }, + "name": { + "description": "Human-readable display label for this model, e.g. `\"Claude Sonnet 4.6\"` or `\"Gemini 3.5 Flash (thinking)\"`. Render this value directly in pickers rather than attempting to parse or transform `id`. Falls back to the `id` string when the catalog entry does not declare an explicit name.", + "example": "Example Name", + "type": "string" + }, + "output_media_formats": { + "description": "MIME types this model can emit as media in chat responses. Empty for text-output models, including image-understanding models that only return text.", + "example": [ + "string" + ], + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "id", + "name", + "default", + "capabilities", + "input_media_formats", + "output_media_formats" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "data" + ], + "type": "object" + } + } + }, + "description": "Successful response" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden — app scope required" + } + }, + "summary": "List available evaluation models", + "x-auth": [ + "publishable_key", + "bearer" + ] + } + }, "/api/v1/ai/image/edits": { "post": { "description": "Applies a text-guided edit to one or more source images and returns the\nresulting image. Pass the source images as base64-encoded objects in the\n`images` array alongside a `prompt` describing the desired modification.\n\nThe underlying provider is selected by the `model` parameter. Omit `model`\nto use the platform default. Size, quality, style, and format options are\nforwarded to the provider as-is; unsupported combinations for a given model\nreturn a 422 error with the provider's error message.\n\nThis endpoint requires authentication. The request is billed against the\nworkspace associated with the authenticated user.\n", @@ -35963,7 +36633,7 @@ }, "properties": { "capabilities": { - "description": "Machine-readable model capabilities. `\"image\"` marks image-input chat, `\"search\"` marks built-in web search, and `\"thinking\"` marks models with configurable reasoning. Empty when the catalog entry declares no special capabilities.", + "description": "Machine-readable model capabilities. `\"image\"` marks image-input chat, `\"search\"` marks built-in web search, `\"temperature\"` marks models that accept the temperature generation parameter, and `\"thinking\"` marks models with configurable reasoning. Empty when the catalog entry declares no special capabilities.", "example": [ "image" ], @@ -35971,6 +36641,7 @@ "enum": [ "image", "search", + "temperature", "thinking" ], "type": "string" @@ -36052,6 +36723,99 @@ ] } }, + "/api/v1/ai/session_token": { + "post": { + "operationId": "post_api_v1_ai_session_token", + "parameters": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "example": { + "entitlement": "llm_calls", + "restrictions": {}, + "ttl": 1, + "user_id": "string" + }, + "properties": { + "entitlement": { + "enum": [ + "llm_calls", + "run_automation" + ], + "example": "llm_calls", + "type": "string" + }, + "restrictions": { + "default": {}, + "example": {}, + "type": "object" + }, + "ttl": { + "default": 300, + "example": 1, + "type": "integer" + }, + "user_id": { + "example": "string", + "type": "string" + } + }, + "required": [ + "user_id" + ], + "type": "object" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "example": { + "expires_at": "string", + "token": "string" + }, + "properties": { + "expires_at": { + "example": "string", + "type": "string" + }, + "token": { + "example": "string", + "type": "string" + } + }, + "required": [ + "token", + "expires_at" + ], + "type": "object" + } + } + }, + "description": "Successful response" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + }, + "422": { + "description": "Invalid parameters" + } + }, + "summary": "Mint a principal-bound billing session token", + "x-auth": [ + "publishable_key", + "bearer" + ] + } + }, "/api/v1/artifacts": { "post": { "description": "Creates a new artifact and stores its file content. A file payload is required;\nsupply it via the `file.data` (Base64-encoded by default), `file.filename`, and\n`file.mime_type` fields. The artifact is scoped to the owner resolved from the\nrequest body — either a team, a user, or an explicit system owner. When no\nowner is supplied and the viewer is an authenticated user, the artifact\ndefaults to that user.\n\nFor company-readable snapshots, pass `system: true` and `org`. Organization\nmembers can read these artifacts; organization admins and system viewers can\ncreate them. Scripts may supply text directly using `file.encoding: \"utf8\"`.\n\nOptionally associate the artifact with an existing thread or agent by passing\n`thread` or `agent`. Legacy requests that wrap fields in an `artifact` object\nare still accepted.\n", @@ -36318,6 +37082,7 @@ "description": "An example description.", "file": { "data": "string", + "encoding": "base64", "filename": "string", "mime_type": "application/json" }, @@ -36338,15 +37103,25 @@ "description": "Replacement file payload. Omit to leave the current file unchanged.", "example": { "data": "string", + "encoding": "base64", "filename": "string", "mime_type": "application/json" }, "properties": { "data": { - "description": "Base64-encoded binary content.", + "description": "File content encoded according to file.encoding.", "example": "string", "type": "string" }, + "encoding": { + "description": "Data encoding; defaults to base64. Use utf8 for script-generated text.", + "enum": [ + "base64", + "utf8" + ], + "example": "base64", + "type": "string" + }, "filename": { "description": "Original filename for the uploaded file.", "example": "string", @@ -38131,6 +38906,9 @@ }, "422": { "description": "Validation failed" + }, + "503": { + "description": "Object storage unavailable" } }, "summary": "Create a config", @@ -40619,7 +41397,7 @@ ] }, "put": { - "description": "Updates the fields of an existing custom object and returns the updated\nobject along with its new version number. The authenticated viewer must have\npermission to modify the object.\n\nYou may supply `fields` (a full or partial key-value map to merge into the\nobject), `field_ops` (granular array operations per field), `acl`, or any\ncompatible combination. The same field name must not appear in both\n`fields` and `field_ops`, which returns 422. Returns 404 if the object does\nnot exist or has been deleted.\n", + "description": "Updates the fields of an existing custom object and returns the updated\nobject along with its new version number. The authenticated viewer must have\npermission to modify the object.\n\nYou may supply `fields` (a full or partial key-value map to merge into the\nobject), `field_ops` (granular array operations per field), `acl`, or any\ncompatible combination. The same field name must not appear in both\n`fields` and `field_ops`, which returns 422. Returns 404 if the object does\nnot exist or has been deleted.\n\nUse `expected_version` for optimistic concurrency: if the object's current\n`aggregate_version` does not match, the request returns 409 and does not\nretry the caller write. Omit it to keep the existing OCC merge retry.\n", "operationId": "put_api_v1_custom_objects__object", "parameters": [ { @@ -40666,6 +41444,7 @@ } ] }, + "expected_version": 1, "field_ops": {}, "fields": {}, "type": "string" @@ -40844,6 +41623,11 @@ }, "type": "object" }, + "expected_version": { + "description": "Version number the caller expects to be current. If the object's actual current version does not match, the request returns 409 to signal a concurrent modification. Omit to skip optimistic locking and keep the existing OCC merge retry.", + "example": 1, + "type": "integer" + }, "field_ops": { "description": "Granular array operations to apply per field (e.g. append, prepend, remove). A field must not appear in both `fields` and `field_ops`.", "example": {}, @@ -41227,6 +42011,9 @@ "404": { "description": "Not found" }, + "409": { + "description": "Conflict - custom object version changed" + }, "422": { "description": "Validation failed" } @@ -42766,7 +43553,7 @@ }, "/api/v1/files": { "post": { - "description": "Creates a new file from base64-encoded content and returns the resulting file object,\nincluding a signed download URL. Use this endpoint to store images, documents, or\nother binary assets that can then be referenced by agents, teams, or users.\n\nApp scope is derived from the authenticated viewer's bearer token or publishable key.\nYou may optionally associate the file with an organization, team, user, or agent by\npassing the corresponding ID. If no owner is specified and the viewer is a user, the\nfile is automatically attributed to that user.\n\nPass `share: true` to additionally mint a stable public URL for the file\n(returned as `share_url`), fetchable by anyone without authentication — for\nexample to embed an uploaded image in a GitHub PR body or other external\nmarkdown. The URL does not expire. Sharing is revoked by setting\n`share: false` on `PATCH /api/v1/files/:file` with the same credential\n(or `archastro update file --unshare`); re-enabling sharing\nreactivates previously issued URLs. Only image content types can be\nshared.\n\nReturns `422` when the `data` field is not valid base64, the changeset is\ninvalid, or `share` is requested for a non-image content type.\nReturns `403` when the request lacks the required app scope.\n", + "description": "Creates a new file from base64-encoded content and returns the resulting file object,\nincluding a signed download URL. Use this endpoint to store images, documents, or\nother binary assets that can then be referenced by agents, teams, or users.\n\nThe JSON body uses Platform's default 8,000,000-byte parser budget; the\nArchDev Platform proxy has a separate 32 MiB request cap. Base64 requires\n`4 * ceil(binary_bytes / 3)` bytes, plus the UTF-8 JSON envelope (including\nfilename, owner IDs, escaping and other fields). For an envelope of E bytes,\nbudget at most `3 * floor((8,000,000 - E) / 4)` binary bytes: less than\n6,000,000 bytes (about 5.72 MiB). Do not rely on parser chunk overshoot.\nOversized JSON requests are rejected with HTTP 413 before upload processing.\n\nApp scope is derived from the authenticated viewer's bearer token or publishable key.\nYou may optionally associate the file with an organization, team, user, or agent by\npassing the corresponding ID. If no owner is specified and the viewer is a user, the\nfile is automatically attributed to that user.\n\nPass `share: true` to additionally mint a stable public URL for the file\n(returned as `share_url`), fetchable by anyone without authentication — for\nexample to embed an uploaded image in a GitHub PR body or other external\nmarkdown. The URL does not expire. Sharing is revoked by setting\n`share: false` on `PATCH /api/v1/files/:file` with the same credential\n(or `archastro update file --unshare`); re-enabling sharing\nreactivates previously issued URLs. Only image content types can be\nshared.\n\nReturns `422` when the `data` field is not valid base64, the changeset is\ninvalid, or `share` is requested for a non-image content type.\nReturns `403` when the request lacks the required app scope.\n", "operationId": "post_api_v1_files", "parameters": [], "requestBody": { @@ -45989,64 +46776,5843 @@ "example": "acme.com", "type": "string" }, - "id": { - "description": "Organization ID (`org_...`).", - "example": "org_0aBcDeFgHiJkLmNoPqRsTu", + "id": { + "description": "Organization ID (`org_...`).", + "example": "org_0aBcDeFgHiJkLmNoPqRsTu", + "type": "string" + }, + "kind": { + "description": "Whether this is a company-domain org or a person-owned personal org.", + "enum": [ + "company", + "personal" + ], + "example": "company", + "type": "string" + }, + "name": { + "description": "Display name of the organization.", + "example": "Example Name", + "type": "string" + } + }, + "required": [ + "id", + "name", + "kind" + ], + "type": "object" + }, + "type": "array" + }, + "has_next": { + "description": "`true` when a subsequent page exists; `false` on the last page.", + "example": true, + "type": "boolean" + }, + "has_prev": { + "description": "`true` when a previous page exists; `false` on the first page.", + "example": true, + "type": "boolean" + }, + "page": { + "description": "The current page number returned.", + "example": 1, + "type": "integer" + }, + "page_size": { + "description": "The number of results per page used for this response.", + "example": 1, + "type": "integer" + }, + "total_entries": { + "description": "Total number of organizations matching the query across all pages.", + "example": 1, + "type": "integer" + }, + "total_pages": { + "description": "Total number of pages for the current query and page size.", + "example": 1, + "type": "integer" + } + }, + "required": [ + "data" + ], + "type": "object" + } + } + }, + "description": "Successful response" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "App-scoped token required. Use a token scoped to the target app." + } + }, + "summary": "Search organizations", + "x-auth": [ + "publishable_key", + "bearer" + ] + } + }, + "/api/v1/orgs/{org}/artifacts": { + "get": { + "description": "Returns completed system-owned organization snapshots, newest first. Private user, team, agent and thread artifacts are excluded.", + "operationId": "get_api_v1_orgs__org_artifacts", + "parameters": [ + { + "description": "Organization ID.", + "example": "string", + "in": "path", + "name": "org", + "required": true, + "schema": { + "type": "string" + } + }, + { + "description": "Maximum snapshots returned, from 1 to 100.", + "example": 1, + "in": "query", + "name": "limit", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "description": "Opaque cursor for the next page of older snapshots.", + "example": "string", + "in": "query", + "name": "after_cursor", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Exact, case-sensitive grouping key.", + "example": "string", + "in": "query", + "name": "group_key", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Nonempty literal group prefix; mutually exclusive with group_key.", + "example": "string", + "in": "query", + "name": "group_key_prefix", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "example": { + "after_cursor": "string", + "before_cursor": "string", + "data": [ + { + "agent": "agt_0aBcDeFgHiJkLmNoPqRsTu", + "content_type": "application/json", + "created_at": "2024-01-01T00:00:00Z", + "current_version": "afv_0aBcDeFgHiJkLmNoPqRsTu", + "description": "An example description.", + "file": "string", + "file_name": "Example Name", + "file_url": "https://example.com", + "group_key": "string", + "id": "art_0aBcDeFgHiJkLmNoPqRsTu", + "image_source": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "sandbox": "string", + "system": true, + "team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "thread": "thr_0aBcDeFgHiJkLmNoPqRsTu", + "updated_at": "2024-01-01T00:00:00Z", + "user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "version": 1 + } + ], + "has_more": true + }, + "properties": { + "after_cursor": { + "example": "string", + "nullable": true, + "type": "string" + }, + "before_cursor": { + "description": "Always null; pagination is forward-only.", + "example": "string", + "nullable": true, + "type": "string" + }, + "data": { + "example": [ + { + "agent": "agt_0aBcDeFgHiJkLmNoPqRsTu", + "content_type": "application/json", + "created_at": "2024-01-01T00:00:00Z", + "current_version": "afv_0aBcDeFgHiJkLmNoPqRsTu", + "description": "An example description.", + "file": "string", + "file_name": "Example Name", + "file_url": "https://example.com", + "group_key": "string", + "id": "art_0aBcDeFgHiJkLmNoPqRsTu", + "image_source": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "sandbox": "string", + "system": true, + "team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "thread": "thr_0aBcDeFgHiJkLmNoPqRsTu", + "updated_at": "2024-01-01T00:00:00Z", + "user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "version": 1 + } + ], + "items": { + "description": "A versioned artifact produced or managed by an agent, such as a generated file, report, or code output.", + "example": { + "agent": "agt_0aBcDeFgHiJkLmNoPqRsTu", + "content_type": "application/json", + "created_at": "2024-01-01T00:00:00Z", + "current_version": "afv_0aBcDeFgHiJkLmNoPqRsTu", + "description": "An example description.", + "file": "string", + "file_name": "Example Name", + "file_url": "https://example.com", + "group_key": "string", + "id": "art_0aBcDeFgHiJkLmNoPqRsTu", + "image_source": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "sandbox": "string", + "system": true, + "team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "thread": "thr_0aBcDeFgHiJkLmNoPqRsTu", + "updated_at": "2024-01-01T00:00:00Z", + "user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "version": 1 + }, + "properties": { + "agent": { + "description": "ID of the agent that produced this artifact (`agt_...`). `null` if not agent-produced.", + "example": "agt_0aBcDeFgHiJkLmNoPqRsTu", + "type": "string" + }, + "content_type": { + "description": "MIME type of the current version's file, e.g. `\"text/csv\"` or `\"image/png\"`. `null` if no file is attached.", + "example": "application/json", + "type": "string" + }, + "created_at": { + "description": "When the artifact was first created (ISO 8601).", + "example": "2024-01-01T00:00:00Z", + "format": "date-time", + "type": "string" + }, + "current_version": { + "description": "ID of the current (latest published) artifact version (`artv_...`). `null` if no version has been published.", + "example": "afv_0aBcDeFgHiJkLmNoPqRsTu", + "type": "string" + }, + "description": { + "description": "Optional longer description of the artifact's contents or purpose. `null` if not set.", + "example": "An example description.", + "type": "string" + }, + "file": { + "description": "Storage file ID for the current version (`fil_...`). `null` if no file is attached.", + "example": "string", + "type": "string" + }, + "file_name": { + "description": "Original filename of the current version's file, e.g. `\"output.csv\"`. `null` if no file is attached.", + "example": "Example Name", + "type": "string" + }, + "file_url": { + "description": "Short-lived signed URL for downloading the current version's file. `null` if no file is attached.", + "example": "https://example.com", + "type": "string" + }, + "group_key": { + "description": "Optional nonunique, case-sensitive grouping key, limited to 1024 UTF-8 bytes. Null when unset; belongs to the artifact, not a content version.", + "example": "string", + "nullable": true, + "type": "string" + }, + "id": { + "description": "Artifact ID (`art_...`).", + "example": "art_0aBcDeFgHiJkLmNoPqRsTu", + "type": "string" + }, + "image_source": { + "description": "Image source metadata for rendering the current version's file inline. Present only when `content_type` starts with `\"image/\"`. `null` otherwise.", + "example": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "properties": { + "file": { + "description": "ID of the underlying storage file (`fil_...`). `null` when the image is not backed by a platform storage file.", + "example": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "height": { + "description": "Height of the image in pixels. `null` if not known.", + "example": 600, + "nullable": true, + "type": "integer" + }, + "media": { + "description": "ID of the associated media record (`med_...`). `null` when the image is not linked to a media entity.", + "example": "med_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "mime_type": { + "description": "MIME type of the image, e.g. `\"image/png\"` or `\"image/jpeg\"`. `null` if not known.", + "example": "application/json", + "nullable": true, + "type": "string" + }, + "refresh_url": { + "description": "Endpoint URL you can call to obtain a fresh signed `url` when the current one has expired. `null` if the URL does not require refreshing.", + "example": "https://example.com", + "nullable": true, + "type": "string" + }, + "url": { + "description": "Signed or public URL for downloading the image. May be time-limited; use `refresh_url` to obtain a new URL when this one expires.", + "example": "https://example.com", + "nullable": true, + "type": "string" + }, + "width": { + "description": "Width of the image in pixels. `null` if not known.", + "example": 800, + "nullable": true, + "type": "integer" + } + }, + "type": "object" + }, + "name": { + "description": "Human-readable name for the artifact, e.g. `\"Q2 Report\"`. `null` if not set.", + "example": "Example Name", + "type": "string" + }, + "org": { + "description": "ID of the organization this artifact belongs to (`org_...`).", + "example": "org_0aBcDeFgHiJkLmNoPqRsTu", + "type": "string" + }, + "sandbox": { + "description": "Identifier of the sandbox environment associated with this artifact. `null` if not sandbox-scoped.", + "example": "string", + "type": "string" + }, + "system": { + "description": "True when the artifact has no user, team, or agent owner. An organization may own a system artifact.", + "example": true, + "type": "boolean" + }, + "team": { + "description": "ID of the team that owns this artifact (`tea_...`). `null` if not team-scoped.", + "example": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "type": "string" + }, + "thread": { + "description": "ID of the thread in which this artifact was created (`thr_...`). `null` if not thread-scoped.", + "example": "thr_0aBcDeFgHiJkLmNoPqRsTu", + "type": "string" + }, + "updated_at": { + "description": "When the artifact record was last modified (ISO 8601).", + "example": "2024-01-01T00:00:00Z", + "format": "date-time", + "type": "string" + }, + "user": { + "description": "ID of the user who created this artifact (`usr_...`). `null` if not user-scoped.", + "example": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "type": "string" + }, + "version": { + "description": "Current version number of the artifact. Increments each time a new version is published.", + "example": 1, + "type": "integer" + } + }, + "required": [ + "id" + ], + "type": "object" + }, + "type": "array" + }, + "has_more": { + "example": true, + "type": "boolean" + } + }, + "required": [ + "data", + "has_more" + ], + "type": "object" + } + } + }, + "description": "Successful response" + }, + "400": { + "description": "Invalid group filters; Invalid cursor" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Organization not found" + } + }, + "summary": "List completed organization artifacts", + "x-auth": [ + "publishable_key", + "bearer" + ] + } + }, + "/api/v1/orgs/{org}/linked_accounts": { + "get": { + "description": "Returns the GitHub login each user in the organization signed in with, so\nclients can tell that a pull request's author and a Platform user are the\nsame person. Users who never signed in with GitHub are absent. Any viewer\nacting within the organization can list them; other viewers get 404.\n\nPass `user` to look up specific users instead of listing the whole\norganization. Results are ordered by user and paginated forward with\n`after_cursor`.\n", + "operationId": "get_api_v1_orgs__org_linked_accounts", + "parameters": [ + { + "description": "Organization ID (`org_...`) whose linked accounts should be listed.", + "example": "string", + "in": "path", + "name": "org", + "required": true, + "schema": { + "type": "string" + } + }, + { + "description": "Up to 100 user IDs (`usr_...`) to look up. Omit to list every user in the organization. Users in the list who are outside the organization or have no linked account are absent.", + "example": [ + "string" + ], + "in": "query", + "name": "user", + "required": false, + "schema": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + { + "description": "Maximum accounts returned, from 1 to 100.", + "example": 1, + "in": "query", + "name": "limit", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "description": "Opaque cursor for the next page.", + "example": "string", + "in": "query", + "name": "after_cursor", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "description": "One page of the organization's linked accounts.", + "example": { + "after_cursor": "string", + "before_cursor": "string", + "data": [ + { + "account_id": "octocat", + "provider": "github", + "user": "string" + } + ], + "has_more": true + }, + "properties": { + "after_cursor": { + "example": "string", + "nullable": true, + "type": "string" + }, + "before_cursor": { + "description": "Always null; pagination is forward-only.", + "example": "string", + "nullable": true, + "type": "string" + }, + "data": { + "description": "Linked accounts, by user.", + "example": [ + { + "account_id": "octocat", + "provider": "github", + "user": "string" + } + ], + "items": { + "description": "An account on another service that a user proved is theirs by signing in with it.", + "example": { + "account_id": "octocat", + "provider": "github", + "user": "string" + }, + "properties": { + "account_id": { + "description": "The service's name for the account: the login, for GitHub.", + "example": "octocat", + "type": "string" + }, + "provider": { + "description": "Service the account is on. Currently always `\"github\"`.", + "example": "github", + "type": "string" + }, + "user": { + "description": "User ID (`usr_...`) the account belongs to.", + "example": "string", + "type": "string" + } + }, + "required": [ + "user", + "provider", + "account_id" + ], + "type": "object" + }, + "type": "array" + }, + "has_more": { + "example": true, + "type": "boolean" + } + }, + "required": [ + "data", + "has_more" + ], + "type": "object" + } + } + }, + "description": "Successful response" + }, + "400": { + "description": "Invalid limit or user IDs; Invalid cursor" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Organization not found" + } + }, + "summary": "List an organization's linked accounts", + "x-auth": [ + "publishable_key", + "bearer" + ] + } + }, + "/api/v1/orgs/{org}/threads": { + "get": { + "description": "Returns org-visibility threads for the specified organization. Every member\nof the organization can list these threads; they require no team membership.\nApp-scoped developer tokens for the organization's app can list them too.\n", + "operationId": "get_api_v1_orgs__org_threads", + "parameters": [ + { + "description": "Organization ID (`org_...`) whose org-visibility threads should be listed.", + "example": "string", + "in": "path", + "name": "org", + "required": true, + "schema": { + "type": "string" + } + }, + { + "description": "Optional exact thread key, for example `archdev-room`.", + "example": "string", + "in": "query", + "name": "key", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "description": "Response envelope containing the organization's threads.", + "example": { + "data": [ + { + "agent_user": "agi_0aBcDeFgHiJkLmNoPqRsTu", + "created_at": "2024-01-01T00:00:00Z", + "creator": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "description": "An example description.", + "id": "string", + "is_channel": true, + "is_default": true, + "is_transient": true, + "is_unlisted": true, + "key": "string", + "kind": "string", + "last_activity": "2024-01-01T00:00:00Z", + "last_message_preview": "Sounds good — I'll ship the fix tomorrow.", + "last_message_sender": "Alice Chen", + "metadata": { + "key": "value" + }, + "muted": true, + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "parent_message": { + "acl": { + "add": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "grants": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "remove": [ + { + "principal": "string", + "principal_type": "user" + } + ] + }, + "actors": [ + { + "alias": "alice", + "id": "user-usr_01j3k5m7n9p2r4s6t8v0w1x2", + "name": "Example Name", + "profile_picture": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + } + } + ], + "agent": "agi_0aBcDeFgHiJkLmNoPqRsTu", + "agent_mode": "cli", + "attachments": [ + { + "content_type": "application/json", + "description": "An example description.", + "filename": "string", + "height": 1, + "id": "string", + "image_height": 1, + "image_source": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "image_url": "https://example.com", + "image_width": 1, + "key": "string", + "media_type": "application/json", + "name": "Example Name", + "object": {}, + "title": "Example Title", + "type": "file", + "url": "https://example.com", + "variants": [ + { + "content_type": "application/json", + "created_at": "2024-01-01T00:00:00Z", + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "filename": "string", + "height": 600, + "id": "mvr_0aBcDeFgHiJkLmNoPqRsTu", + "image_source": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "updated_at": "2024-01-01T00:00:00Z", + "url": "https://example.com", + "variant_key": "original", + "width": 800 + } + ], + "version": 1, + "width": 1 + } + ], + "branched_thread": "string", + "content": "Hello, how can I help you today?", + "context": [ + { + "attributes": {}, + "content": "string", + "title": "PR #10458", + "type": "archdev.pull_request" + } + ], + "created_at": "2024-01-01T00:00:00Z", + "has_replies": true, + "id": "msg_0aBcDeFgHiJkLmNoPqRsTu", + "idempotency_key": "01234567-89ab-cdef-0123-456789abcdef", + "is_deleted": true, + "legacy_agent": "string", + "metadata": { + "key": "value" + }, + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "reactions": [ + { + "payload": { + "key": "value" + }, + "type": "emoji_reaction", + "user": "string" + } + ], + "rendering_mode": "reply", + "replies": [ + {} + ], + "replies_after_cursor": "string", + "replies_before_cursor": "string", + "reply_count": 1, + "reply_to": {}, + "root_message_id": "string", + "sandbox": "string", + "team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "thread": "string", + "type": "note", + "user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "visibility": "default" + }, + "participant": [ + "string" + ], + "participants": [ + { + "alias": "jdoe", + "app": "dap_0aBcDeFgHiJkLmNoPqRsTu", + "app_name": "Example Name", + "created_by_agent_user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_developer": "dva_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "email": "user@example.com", + "id": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "is_system_user": true, + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_name": "Example Name", + "org_role": "member", + "org_slug": "example-slug", + "sandbox": "dsb_0aBcDeFgHiJkLmNoPqRsTu", + "sandbox_name": "Example Name" + } + ], + "participating_actor": [ + "string" + ], + "participating_agents": [ + { + "acl": { + "add": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "grants": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "remove": [ + { + "principal": "string", + "principal_type": "user" + } + ] + }, + "app": "dap_0aBcDeFgHiJkLmNoPqRsTu", + "created_at": "2024-01-01T00:00:00Z", + "default_model": "claude-3-7-sonnet-latest", + "description": "An example description.", + "email": "user@example.com", + "id": "agi_0aBcDeFgHiJkLmNoPqRsTu", + "identity": "You are a helpful assistant that answers questions about ArchAstro products.", + "last_applied_template_config": "cfg_0aBcDeFgHiJkLmNoPqRsTu", + "lookup_key": "string", + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_name": "Example Name", + "originator": "deploy-pipeline", + "phone_number": "+15555550123", + "sandbox": "dsb_0aBcDeFgHiJkLmNoPqRsTu", + "source_solution": { + "current_solution": { + "category_keys": [ + "string" + ], + "created_at": "2024-01-01T00:00:00Z", + "description": "An example description.", + "events": {}, + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "image_url": "https://example.com", + "installed_config_ids": [ + "string" + ], + "kind": "Solution", + "latest_solution": "id_0aBcDeFgHiJkLmNoPqRsTu", + "latest_version": "1.0.0", + "lookup_key": "string", + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_logo": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "org_name": "Example Name", + "org_slug": "example-slug", + "owners": [ + "string" + ], + "readme_url": "https://example.com", + "screenshot_urls": [ + "https://example.com" + ], + "solution_id": "01234567-89ab-cdef-0123-456789abcdef", + "solution_version": "1.2.0", + "tag_keys": [ + "string" + ], + "template_kind": "AgentTemplate", + "templates": [ + { + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "AgentTemplate", + "lookup_key": "string", + "name": "Example Name", + "readme_url": "https://example.com", + "virtual_path": "string" + } + ], + "updated_at": "2024-01-01T00:00:00Z", + "upgrade_available": true, + "virtual_path": "string" + }, + "solution": { + "category_keys": [ + "string" + ], + "created_at": "2024-01-01T00:00:00Z", + "description": "An example description.", + "events": {}, + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "image_url": "https://example.com", + "installed_config_ids": [ + "string" + ], + "kind": "Solution", + "latest_solution": "id_0aBcDeFgHiJkLmNoPqRsTu", + "latest_version": "1.0.0", + "lookup_key": "string", + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_logo": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "org_name": "Example Name", + "org_slug": "example-slug", + "owners": [ + "string" + ], + "readme_url": "https://example.com", + "screenshot_urls": [ + "https://example.com" + ], + "solution_id": "01234567-89ab-cdef-0123-456789abcdef", + "solution_version": "1.2.0", + "tag_keys": [ + "string" + ], + "template_kind": "AgentTemplate", + "templates": [ + { + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "AgentTemplate", + "lookup_key": "string", + "name": "Example Name", + "readme_url": "https://example.com", + "virtual_path": "string" + } + ], + "updated_at": "2024-01-01T00:00:00Z", + "upgrade_available": true, + "virtual_path": "string" + }, + "template": { + "created_at": "2024-01-01T00:00:00Z", + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "agent_tool_template", + "lookup_key": "string", + "name": "Example Name", + "updated_at": "2024-01-01T00:00:00Z", + "virtual_path": "string" + } + }, + "team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "template_upgrade_available": true, + "updated_at": "2024-01-01T00:00:00Z", + "user": "usr_0aBcDeFgHiJkLmNoPqRsTu" + } + ], + "role": "member", + "sandbox": "dsb_0aBcDeFgHiJkLmNoPqRsTu", + "settings": { + "agent_enabled": true + }, + "slug": "example-slug", + "sub_threads": [ + {} + ], + "tags": [ + "blocked", + "needs-review" + ], + "team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "title": "Example Title", + "ttl": "2026-08-15T12:00:00", + "unread_count": 5, + "updated_at": "2024-01-01T00:00:00Z", + "user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "visibility": "team" + } + ] + }, + "properties": { + "data": { + "description": "Array of org-visibility thread objects.", + "example": [ + { + "agent_user": "agi_0aBcDeFgHiJkLmNoPqRsTu", + "created_at": "2024-01-01T00:00:00Z", + "creator": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "description": "An example description.", + "id": "string", + "is_channel": true, + "is_default": true, + "is_transient": true, + "is_unlisted": true, + "key": "string", + "kind": "string", + "last_activity": "2024-01-01T00:00:00Z", + "last_message_preview": "Sounds good — I'll ship the fix tomorrow.", + "last_message_sender": "Alice Chen", + "metadata": { + "key": "value" + }, + "muted": true, + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "parent_message": { + "acl": { + "add": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "grants": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "remove": [ + { + "principal": "string", + "principal_type": "user" + } + ] + }, + "actors": [ + { + "alias": "alice", + "id": "user-usr_01j3k5m7n9p2r4s6t8v0w1x2", + "name": "Example Name", + "profile_picture": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + } + } + ], + "agent": "agi_0aBcDeFgHiJkLmNoPqRsTu", + "agent_mode": "cli", + "attachments": [ + { + "content_type": "application/json", + "description": "An example description.", + "filename": "string", + "height": 1, + "id": "string", + "image_height": 1, + "image_source": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "image_url": "https://example.com", + "image_width": 1, + "key": "string", + "media_type": "application/json", + "name": "Example Name", + "object": {}, + "title": "Example Title", + "type": "file", + "url": "https://example.com", + "variants": [ + { + "content_type": "application/json", + "created_at": "2024-01-01T00:00:00Z", + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "filename": "string", + "height": 600, + "id": "mvr_0aBcDeFgHiJkLmNoPqRsTu", + "image_source": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "updated_at": "2024-01-01T00:00:00Z", + "url": "https://example.com", + "variant_key": "original", + "width": 800 + } + ], + "version": 1, + "width": 1 + } + ], + "branched_thread": "string", + "content": "Hello, how can I help you today?", + "context": [ + { + "attributes": {}, + "content": "string", + "title": "PR #10458", + "type": "archdev.pull_request" + } + ], + "created_at": "2024-01-01T00:00:00Z", + "has_replies": true, + "id": "msg_0aBcDeFgHiJkLmNoPqRsTu", + "idempotency_key": "01234567-89ab-cdef-0123-456789abcdef", + "is_deleted": true, + "legacy_agent": "string", + "metadata": { + "key": "value" + }, + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "reactions": [ + { + "payload": { + "key": "value" + }, + "type": "emoji_reaction", + "user": "string" + } + ], + "rendering_mode": "reply", + "replies": [ + {} + ], + "replies_after_cursor": "string", + "replies_before_cursor": "string", + "reply_count": 1, + "reply_to": {}, + "root_message_id": "string", + "sandbox": "string", + "team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "thread": "string", + "type": "note", + "user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "visibility": "default" + }, + "participant": [ + "string" + ], + "participants": [ + { + "alias": "jdoe", + "app": "dap_0aBcDeFgHiJkLmNoPqRsTu", + "app_name": "Example Name", + "created_by_agent_user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_developer": "dva_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "email": "user@example.com", + "id": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "is_system_user": true, + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_name": "Example Name", + "org_role": "member", + "org_slug": "example-slug", + "sandbox": "dsb_0aBcDeFgHiJkLmNoPqRsTu", + "sandbox_name": "Example Name" + } + ], + "participating_actor": [ + "string" + ], + "participating_agents": [ + { + "acl": { + "add": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "grants": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "remove": [ + { + "principal": "string", + "principal_type": "user" + } + ] + }, + "app": "dap_0aBcDeFgHiJkLmNoPqRsTu", + "created_at": "2024-01-01T00:00:00Z", + "default_model": "claude-3-7-sonnet-latest", + "description": "An example description.", + "email": "user@example.com", + "id": "agi_0aBcDeFgHiJkLmNoPqRsTu", + "identity": "You are a helpful assistant that answers questions about ArchAstro products.", + "last_applied_template_config": "cfg_0aBcDeFgHiJkLmNoPqRsTu", + "lookup_key": "string", + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_name": "Example Name", + "originator": "deploy-pipeline", + "phone_number": "+15555550123", + "sandbox": "dsb_0aBcDeFgHiJkLmNoPqRsTu", + "source_solution": { + "current_solution": { + "category_keys": [ + "string" + ], + "created_at": "2024-01-01T00:00:00Z", + "description": "An example description.", + "events": {}, + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "image_url": "https://example.com", + "installed_config_ids": [ + "string" + ], + "kind": "Solution", + "latest_solution": "id_0aBcDeFgHiJkLmNoPqRsTu", + "latest_version": "1.0.0", + "lookup_key": "string", + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_logo": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "org_name": "Example Name", + "org_slug": "example-slug", + "owners": [ + "string" + ], + "readme_url": "https://example.com", + "screenshot_urls": [ + "https://example.com" + ], + "solution_id": "01234567-89ab-cdef-0123-456789abcdef", + "solution_version": "1.2.0", + "tag_keys": [ + "string" + ], + "template_kind": "AgentTemplate", + "templates": [ + { + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "AgentTemplate", + "lookup_key": "string", + "name": "Example Name", + "readme_url": "https://example.com", + "virtual_path": "string" + } + ], + "updated_at": "2024-01-01T00:00:00Z", + "upgrade_available": true, + "virtual_path": "string" + }, + "solution": { + "category_keys": [ + "string" + ], + "created_at": "2024-01-01T00:00:00Z", + "description": "An example description.", + "events": {}, + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "image_url": "https://example.com", + "installed_config_ids": [ + "string" + ], + "kind": "Solution", + "latest_solution": "id_0aBcDeFgHiJkLmNoPqRsTu", + "latest_version": "1.0.0", + "lookup_key": "string", + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_logo": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "org_name": "Example Name", + "org_slug": "example-slug", + "owners": [ + "string" + ], + "readme_url": "https://example.com", + "screenshot_urls": [ + "https://example.com" + ], + "solution_id": "01234567-89ab-cdef-0123-456789abcdef", + "solution_version": "1.2.0", + "tag_keys": [ + "string" + ], + "template_kind": "AgentTemplate", + "templates": [ + { + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "AgentTemplate", + "lookup_key": "string", + "name": "Example Name", + "readme_url": "https://example.com", + "virtual_path": "string" + } + ], + "updated_at": "2024-01-01T00:00:00Z", + "upgrade_available": true, + "virtual_path": "string" + }, + "template": { + "created_at": "2024-01-01T00:00:00Z", + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "agent_tool_template", + "lookup_key": "string", + "name": "Example Name", + "updated_at": "2024-01-01T00:00:00Z", + "virtual_path": "string" + } + }, + "team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "template_upgrade_available": true, + "updated_at": "2024-01-01T00:00:00Z", + "user": "usr_0aBcDeFgHiJkLmNoPqRsTu" + } + ], + "role": "member", + "sandbox": "dsb_0aBcDeFgHiJkLmNoPqRsTu", + "settings": { + "agent_enabled": true + }, + "slug": "example-slug", + "sub_threads": [ + {} + ], + "tags": [ + "blocked", + "needs-review" + ], + "team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "title": "Example Title", + "ttl": "2026-08-15T12:00:00", + "unread_count": 5, + "updated_at": "2024-01-01T00:00:00Z", + "user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "visibility": "team" + } + ], + "items": { + "description": "A chat thread, representing a conversation channel that can be owned by a user, team, or agent and may contain messages, participants, and AI agent activity.", + "example": { + "agent_user": "agi_0aBcDeFgHiJkLmNoPqRsTu", + "created_at": "string", + "creator": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "description": "An example description.", + "id": "string", + "is_channel": true, + "is_default": true, + "is_transient": true, + "is_unlisted": true, + "key": "string", + "kind": "string", + "last_activity": "string", + "last_message_preview": "Sounds good — I'll ship the fix tomorrow.", + "last_message_sender": "Alice Chen", + "metadata": { + "key": "value" + }, + "muted": true, + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "parent_message": { + "acl": { + "add": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "grants": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "remove": [ + { + "principal": "string", + "principal_type": "user" + } + ] + }, + "actors": [ + { + "alias": "alice", + "id": "user-usr_01j3k5m7n9p2r4s6t8v0w1x2", + "name": "Example Name", + "profile_picture": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + } + } + ], + "agent": "agi_0aBcDeFgHiJkLmNoPqRsTu", + "agent_mode": "cli", + "attachments": [ + { + "content_type": "application/json", + "description": "An example description.", + "filename": "string", + "height": 1, + "id": "string", + "image_height": 1, + "image_source": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "image_url": "https://example.com", + "image_width": 1, + "key": "string", + "media_type": "application/json", + "name": "Example Name", + "object": {}, + "title": "Example Title", + "type": "file", + "url": "https://example.com", + "variants": [ + { + "content_type": "application/json", + "created_at": "2024-01-01T00:00:00Z", + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "filename": "string", + "height": 600, + "id": "mvr_0aBcDeFgHiJkLmNoPqRsTu", + "image_source": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "updated_at": "2024-01-01T00:00:00Z", + "url": "https://example.com", + "variant_key": "original", + "width": 800 + } + ], + "version": 1, + "width": 1 + } + ], + "branched_thread": "string", + "content": "Hello, how can I help you today?", + "context": [ + { + "attributes": {}, + "content": "string", + "title": "PR #10458", + "type": "archdev.pull_request" + } + ], + "created_at": "2024-01-01T00:00:00Z", + "has_replies": true, + "id": "msg_0aBcDeFgHiJkLmNoPqRsTu", + "idempotency_key": "01234567-89ab-cdef-0123-456789abcdef", + "is_deleted": true, + "legacy_agent": "string", + "metadata": { + "key": "value" + }, + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "reactions": [ + { + "payload": { + "key": "value" + }, + "type": "emoji_reaction", + "user": "string" + } + ], + "rendering_mode": "reply", + "replies": [ + {} + ], + "replies_after_cursor": "string", + "replies_before_cursor": "string", + "reply_count": 1, + "reply_to": {}, + "root_message_id": "string", + "sandbox": "string", + "team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "thread": "string", + "type": "note", + "user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "visibility": "default" + }, + "participant": [ + "string" + ], + "participants": [ + { + "alias": "jdoe", + "app": "dap_0aBcDeFgHiJkLmNoPqRsTu", + "app_name": "Example Name", + "created_by_agent_user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_developer": "dva_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "email": "user@example.com", + "id": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "is_system_user": true, + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_name": "Example Name", + "org_role": "member", + "org_slug": "example-slug", + "sandbox": "dsb_0aBcDeFgHiJkLmNoPqRsTu", + "sandbox_name": "Example Name" + } + ], + "participating_actor": [ + "string" + ], + "participating_agents": [ + { + "acl": { + "add": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "grants": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "remove": [ + { + "principal": "string", + "principal_type": "user" + } + ] + }, + "app": "dap_0aBcDeFgHiJkLmNoPqRsTu", + "created_at": "2024-01-01T00:00:00Z", + "default_model": "claude-3-7-sonnet-latest", + "description": "An example description.", + "email": "user@example.com", + "id": "agi_0aBcDeFgHiJkLmNoPqRsTu", + "identity": "You are a helpful assistant that answers questions about ArchAstro products.", + "last_applied_template_config": "cfg_0aBcDeFgHiJkLmNoPqRsTu", + "lookup_key": "string", + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_name": "Example Name", + "originator": "deploy-pipeline", + "phone_number": "+15555550123", + "sandbox": "dsb_0aBcDeFgHiJkLmNoPqRsTu", + "source_solution": { + "current_solution": { + "category_keys": [ + "string" + ], + "created_at": "2024-01-01T00:00:00Z", + "description": "An example description.", + "events": {}, + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "image_url": "https://example.com", + "installed_config_ids": [ + "string" + ], + "kind": "Solution", + "latest_solution": "id_0aBcDeFgHiJkLmNoPqRsTu", + "latest_version": "1.0.0", + "lookup_key": "string", + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_logo": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "org_name": "Example Name", + "org_slug": "example-slug", + "owners": [ + "string" + ], + "readme_url": "https://example.com", + "screenshot_urls": [ + "https://example.com" + ], + "solution_id": "01234567-89ab-cdef-0123-456789abcdef", + "solution_version": "1.2.0", + "tag_keys": [ + "string" + ], + "template_kind": "AgentTemplate", + "templates": [ + { + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "AgentTemplate", + "lookup_key": "string", + "name": "Example Name", + "readme_url": "https://example.com", + "virtual_path": "string" + } + ], + "updated_at": "2024-01-01T00:00:00Z", + "upgrade_available": true, + "virtual_path": "string" + }, + "solution": { + "category_keys": [ + "string" + ], + "created_at": "2024-01-01T00:00:00Z", + "description": "An example description.", + "events": {}, + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "image_url": "https://example.com", + "installed_config_ids": [ + "string" + ], + "kind": "Solution", + "latest_solution": "id_0aBcDeFgHiJkLmNoPqRsTu", + "latest_version": "1.0.0", + "lookup_key": "string", + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_logo": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "org_name": "Example Name", + "org_slug": "example-slug", + "owners": [ + "string" + ], + "readme_url": "https://example.com", + "screenshot_urls": [ + "https://example.com" + ], + "solution_id": "01234567-89ab-cdef-0123-456789abcdef", + "solution_version": "1.2.0", + "tag_keys": [ + "string" + ], + "template_kind": "AgentTemplate", + "templates": [ + { + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "AgentTemplate", + "lookup_key": "string", + "name": "Example Name", + "readme_url": "https://example.com", + "virtual_path": "string" + } + ], + "updated_at": "2024-01-01T00:00:00Z", + "upgrade_available": true, + "virtual_path": "string" + }, + "template": { + "created_at": "2024-01-01T00:00:00Z", + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "agent_tool_template", + "lookup_key": "string", + "name": "Example Name", + "updated_at": "2024-01-01T00:00:00Z", + "virtual_path": "string" + } + }, + "team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "template_upgrade_available": true, + "updated_at": "2024-01-01T00:00:00Z", + "user": "usr_0aBcDeFgHiJkLmNoPqRsTu" + } + ], + "role": "member", + "sandbox": "dsb_0aBcDeFgHiJkLmNoPqRsTu", + "settings": { + "agent_enabled": true + }, + "slug": "example-slug", + "sub_threads": [ + {} + ], + "tags": [ + "blocked", + "needs-review" + ], + "team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "title": "Example Title", + "ttl": "2026-08-15T12:00:00", + "unread_count": 5, + "updated_at": "string", + "user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "visibility": "team" + }, + "properties": { + "agent_user": { + "description": "ID of the agent that owns this thread (`agt_...`). `null` for user-owned or team-owned threads.", + "example": "agi_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "created_at": { + "description": "When the thread was created (ISO 8601).", + "example": "string", + "type": "string" + }, + "creator": { + "description": "User who created this thread. Returns a user ID (`usr_...`) by default, or an expanded user object when the association is loaded. `null` if the creator is unknown.", + "example": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "oneOf": [ + { + "type": "string" + }, + { + "description": "A platform user account. Represents a human or system actor that can own threads, belong to an organization, and interact with the API.", + "example": { + "alias": "jdoe", + "app": "dap_0aBcDeFgHiJkLmNoPqRsTu", + "app_name": "Example Name", + "created_by_agent_user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_developer": "dva_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "email": "user@example.com", + "id": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "is_system_user": true, + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_name": "Example Name", + "org_role": "member", + "org_slug": "example-slug", + "sandbox": "dsb_0aBcDeFgHiJkLmNoPqRsTu", + "sandbox_name": "Example Name" + }, + "properties": { + "alias": { + "description": "Short handle or alias for the user. `null` if not set.", + "example": "jdoe", + "nullable": true, + "type": "string" + }, + "app": { + "description": "ID of the app this user (and their access token) is scoped to (`dap_...`). `null` if the user is not scoped to an app.", + "example": "dap_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "app_name": { + "description": "Display name of the user's app. `null` when the app association was not preloaded by the caller.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "created_by_agent_user": { + "description": "Agent user that created this account (`usr_...`). `null` unless an agent created it.", + "example": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "created_by_developer": { + "description": "Developer account that created this user (`dva_...`). `null` unless created via a developer token.", + "example": "dva_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "created_by_org": { + "description": "Org of the principal that created this user (`org_...`). `null` on legacy rows.", + "example": "org_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "created_by_team": { + "description": "Team that created this user (`tem_...`). `null` unless created as a team.", + "example": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "created_by_user": { + "description": "User who created this account (`usr_...`). `null` on self-signup or legacy rows.", + "example": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "email": { + "description": "Email address of the user.", + "example": "user@example.com", + "nullable": true, + "type": "string" + }, + "id": { + "description": "User ID (`usr_...`).", + "example": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "type": "string" + }, + "is_system_user": { + "description": "`true` if this account is an internal system user rather than a human. System users are created automatically by the platform.", + "example": true, + "type": "boolean" + }, + "metadata": { + "description": "Arbitrary key-value metadata attached to the user. Defaults to an empty object.", + "example": { + "key": "value" + }, + "type": "object" + }, + "name": { + "description": "Full display name of the user. `null` if the user has not set a name.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "org": { + "description": "ID of the organization this user belongs to (`org_...`). `null` if the user is not a member of any organization.", + "example": "org_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "org_name": { + "description": "Display name of the user's organization. `null` when the user is not in an org, or when the org association was not preloaded by the caller.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "org_role": { + "description": "Role of the user within their organization. One of `\"admin\"`, `\"member\"`, or `\"viewer\"`. `null` when the user is not a member of any organization.", + "example": "member", + "nullable": true, + "type": "string" + }, + "org_slug": { + "description": "Stable workspace slug for the user's organization. `null` when the user is not in an org, or when the org association was not preloaded by the caller.", + "example": "example-slug", + "nullable": true, + "type": "string" + }, + "sandbox": { + "description": "ID of the sandbox environment this user is scoped to (`sbx_...`). `null` for production users.", + "example": "dsb_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "sandbox_name": { + "description": "Display name of the user's sandbox environment. `null` for production users, or when the sandbox association was not preloaded by the caller.", + "example": "Example Name", + "nullable": true, + "type": "string" + } + }, + "required": [ + "id" + ], + "type": "object" + } + ] + }, + "description": { + "description": "Optional description or purpose statement for the thread. `null` if not set.", + "example": "An example description.", + "nullable": true, + "type": "string" + }, + "id": { + "description": "Thread ID (`thr_...`).", + "example": "string", + "type": "string" + }, + "is_channel": { + "description": "Whether this thread operates as a channel — a multi-member broadcast-style conversation.", + "example": true, + "type": "boolean" + }, + "is_default": { + "description": "Whether this is the default thread for its owner. Each user or team has at most one default thread.", + "example": true, + "type": "boolean" + }, + "is_transient": { + "description": "Whether this thread is ephemeral and may be deleted automatically after a period of inactivity or when its TTL expires.", + "example": true, + "type": "boolean" + }, + "is_unlisted": { + "description": "Whether this thread is hidden from public discovery. Unlisted threads are accessible only to direct participants.", + "example": true, + "type": "boolean" + }, + "key": { + "description": "Application-defined stable key that uniquely identifies the thread within its scope. Useful for idempotent creation. `null` if not set.", + "example": "string", + "nullable": true, + "type": "string" + }, + "kind": { + "description": "Thread subtype: `\"standard\"` for ordinary threads, `\"personal\"` for a user-and-owned-agents roster, `\"feed\"` for a post feed with inline replies, `\"slack_mirror\"` for the membership-strict mirror of a Slack channel, or `\"slashwork_mirror\"` for the membership-strict mirror of a Slashwork group. `personal` and `feed` are explicit creation options; mirror kinds are server-derived.", + "example": "string", + "nullable": true, + "type": "string" + }, + "last_activity": { + "description": "When the most recent message was posted in this thread, falling back to the thread's creation time if it has no messages. Always populated on thread list endpoints (which order by it, after default threads); `null` on endpoints that don't compute activity enrichment.", + "example": "string", + "nullable": true, + "type": "string" + }, + "last_message_preview": { + "description": "Single-line snippet of the most recent message's text content (first non-empty line, truncated to 140 characters). Populated on thread list endpoints alongside `last_activity`; `null` when the thread has no messages, the latest message has no text content (e.g. attachment-only), or the endpoint doesn't compute activity enrichment.", + "example": "Sounds good — I'll ship the fix tomorrow.", + "nullable": true, + "type": "string" + }, + "last_message_sender": { + "description": "Display name of the sender of the most recent message — the same message `last_message_preview` snippets. Populated on thread list endpoints; `null` when the thread has no messages or the endpoint doesn't compute activity enrichment.", + "example": "Alice Chen", + "nullable": true, + "type": "string" + }, + "metadata": { + "description": "Arbitrary key-value metadata attached to the thread. Shape is application-defined; `null` if no metadata has been set.", + "example": { + "key": "value" + }, + "nullable": true, + "type": "object" + }, + "muted": { + "description": "Whether the authenticated user has muted notifications for this thread. `true` suppresses all notification delivery.", + "example": true, + "type": "boolean" + }, + "org": { + "description": "ID of the organization this thread belongs to (`org_...`). `null` for threads outside an org context.", + "example": "org_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "parent_message": { + "description": "The message that spawned this thread as a sub-thread. `null` for top-level threads.", + "example": { + "acl": { + "add": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "grants": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "remove": [ + { + "principal": "string", + "principal_type": "user" + } + ] + }, + "actors": [ + { + "alias": "alice", + "id": "user-usr_01j3k5m7n9p2r4s6t8v0w1x2", + "name": "Example Name", + "profile_picture": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + } + } + ], + "agent": "agi_0aBcDeFgHiJkLmNoPqRsTu", + "agent_mode": "cli", + "attachments": [ + { + "content_type": "application/json", + "description": "An example description.", + "filename": "string", + "height": 1, + "id": "string", + "image_height": 1, + "image_source": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "image_url": "https://example.com", + "image_width": 1, + "key": "string", + "media_type": "application/json", + "name": "Example Name", + "object": {}, + "title": "Example Title", + "type": "file", + "url": "https://example.com", + "variants": [ + { + "content_type": "application/json", + "created_at": "2024-01-01T00:00:00Z", + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "filename": "string", + "height": 600, + "id": "mvr_0aBcDeFgHiJkLmNoPqRsTu", + "image_source": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "updated_at": "2024-01-01T00:00:00Z", + "url": "https://example.com", + "variant_key": "original", + "width": 800 + } + ], + "version": 1, + "width": 1 + } + ], + "branched_thread": "string", + "content": "Hello, how can I help you today?", + "context": [ + { + "attributes": {}, + "content": "string", + "title": "PR #10458", + "type": "archdev.pull_request" + } + ], + "created_at": "2024-01-01T00:00:00Z", + "has_replies": true, + "id": "msg_0aBcDeFgHiJkLmNoPqRsTu", + "idempotency_key": "01234567-89ab-cdef-0123-456789abcdef", + "is_deleted": true, + "legacy_agent": "string", + "metadata": { + "key": "value" + }, + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "reactions": [ + { + "payload": { + "key": "value" + }, + "type": "emoji_reaction", + "user": "string" + } + ], + "rendering_mode": "reply", + "replies": [ + {} + ], + "replies_after_cursor": "string", + "replies_before_cursor": "string", + "reply_count": 1, + "reply_to": {}, + "root_message_id": "string", + "sandbox": "string", + "team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "thread": "string", + "type": "note", + "user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "visibility": "default" + }, + "nullable": true, + "properties": { + "acl": { + "description": "Access control list for private messages (grants with `read` action). Only returned to resource owners (and privileged/org-admin viewers) via server-side `field_redactions: [acl: :owner]`; `null` for everyone else.", + "example": { + "add": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "grants": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "remove": [ + { + "principal": "string", + "principal_type": "user" + } + ] + }, + "nullable": true, + "properties": { + "add": { + "description": "Patch mode: grants to add or merge into the existing list. Cannot be combined with `grants`.", + "example": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "items": { + "description": "A single access-control grant that pairs a principal with the set of actions it is allowed to perform.", + "example": { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + }, + "properties": { + "actions": { + "description": "Array of action strings the principal is permitted to perform, e.g. `[\"read\", \"write\"]`. Must contain at least one entry.", + "example": [ + "read", + "write" + ], + "items": { + "type": "string" + }, + "type": "array" + }, + "principal": { + "description": "The identifier of the principal. A string ID for `\"user\"`, `\"team\"`, `\"org\"`, and `\"agent\"` types; one of `\"admin\"`, `\"member\"`, or `\"viewer\"` for `\"org_role\"`; omit entirely when `principal_type` is `\"everyone\"`.", + "example": "string", + "type": "string" + }, + "principal_type": { + "description": "The kind of principal receiving the grant. One of `\"user\"`, `\"team\"`, `\"org\"`, `\"org_role\"`, `\"agent\"`, or `\"everyone\"`.", + "example": "user", + "type": "string" + } + }, + "required": [ + "principal_type", + "actions" + ], + "type": "object" + }, + "type": "array" + }, + "grants": { + "description": "Replace mode: the complete new list of grants that replaces all existing entries. Send an empty array (`[]`) to clear all grants. Cannot be combined with `add` or `remove`.", + "example": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "items": { + "description": "A single access-control grant that pairs a principal with the set of actions it is allowed to perform.", + "example": { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + }, + "properties": { + "actions": { + "description": "Array of action strings the principal is permitted to perform, e.g. `[\"read\", \"write\"]`. Must contain at least one entry.", + "example": [ + "read", + "write" + ], + "items": { + "type": "string" + }, + "type": "array" + }, + "principal": { + "description": "The identifier of the principal. A string ID for `\"user\"`, `\"team\"`, `\"org\"`, and `\"agent\"` types; one of `\"admin\"`, `\"member\"`, or `\"viewer\"` for `\"org_role\"`; omit entirely when `principal_type` is `\"everyone\"`.", + "example": "string", + "type": "string" + }, + "principal_type": { + "description": "The kind of principal receiving the grant. One of `\"user\"`, `\"team\"`, `\"org\"`, `\"org_role\"`, `\"agent\"`, or `\"everyone\"`.", + "example": "user", + "type": "string" + } + }, + "required": [ + "principal_type", + "actions" + ], + "type": "object" + }, + "type": "array" + }, + "remove": { + "description": "Patch mode: principals whose grants should be removed from the existing list. Cannot be combined with `grants`.", + "example": [ + { + "principal": "string", + "principal_type": "user" + } + ], + "items": { + "description": "Identifies a principal to be removed from an access-control list.", + "example": { + "principal": "string", + "principal_type": "user" + }, + "properties": { + "principal": { + "description": "The identifier of the principal to remove. A string ID for `\"user\"`, `\"team\"`, `\"org\"`, and `\"agent\"` types; one of `\"admin\"`, `\"member\"`, or `\"viewer\"` for `\"org_role\"`. Omit when `principal_type` is `\"everyone\"`.", + "example": "string", + "type": "string" + }, + "principal_type": { + "description": "The kind of principal to remove. One of `\"user\"`, `\"team\"`, `\"org\"`, `\"org_role\"`, `\"agent\"`, or `\"everyone\"`.", + "example": "user", + "type": "string" + } + }, + "required": [ + "principal_type" + ], + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "actors": { + "description": "Resolved actor descriptors for the message sender, combining identity and display metadata. Always contains exactly one entry.", + "example": [ + { + "alias": "alice", + "id": "user-usr_01j3k5m7n9p2r4s6t8v0w1x2", + "name": "Example Name", + "profile_picture": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + } + } + ], + "items": { + "description": "The entity that authored a message, either a human user or an agent.", + "example": { + "alias": "alice", + "id": "user-usr_01j3k5m7n9p2r4s6t8v0w1x2", + "name": "Example Name", + "profile_picture": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + } + }, + "properties": { + "alias": { + "description": "Short handle or alias for the actor, used as an alternate display identifier. `null` if not configured.", + "example": "alice", + "nullable": true, + "type": "string" + }, + "id": { + "description": "Composite actor identifier. Format is `\"user-\"` for human users or `\"agent-\"` for agents.", + "example": "user-usr_01j3k5m7n9p2r4s6t8v0w1x2", + "nullable": true, + "type": "string" + }, + "name": { + "description": "Display name of the actor shown in the UI. `null` if no name is set.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "profile_picture": { + "description": "Profile picture for the actor. `null` if the actor has no profile picture.", + "example": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "nullable": true, + "properties": { + "file": { + "description": "ID of the underlying storage file (`fil_...`). `null` when the image is not backed by a platform storage file.", + "example": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "height": { + "description": "Height of the image in pixels. `null` if not known.", + "example": 600, + "nullable": true, + "type": "integer" + }, + "media": { + "description": "ID of the associated media record (`med_...`). `null` when the image is not linked to a media entity.", + "example": "med_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "mime_type": { + "description": "MIME type of the image, e.g. `\"image/png\"` or `\"image/jpeg\"`. `null` if not known.", + "example": "application/json", + "nullable": true, + "type": "string" + }, + "refresh_url": { + "description": "Endpoint URL you can call to obtain a fresh signed `url` when the current one has expired. `null` if the URL does not require refreshing.", + "example": "https://example.com", + "nullable": true, + "type": "string" + }, + "url": { + "description": "Signed or public URL for downloading the image. May be time-limited; use `refresh_url` to obtain a new URL when this one expires.", + "example": "https://example.com", + "nullable": true, + "type": "string" + }, + "width": { + "description": "Width of the image in pixels. `null` if not known.", + "example": 800, + "nullable": true, + "type": "integer" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "type": "array" + }, + "agent": { + "description": "ID of the agent user that sent this message (`agi_...`). `null` for messages sent by human users.", + "example": "agi_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "agent_mode": { + "description": "Local agent execution mode for this message. One of `cli`, `embedded`, or `null` when the message was not created by a local agent execution path.", + "enum": [ + "cli", + "embedded" + ], + "example": "cli", + "nullable": true, + "type": "string" + }, + "attachments": { + "description": "Files, links, tasks, media, artifacts, and actions attached to this message. Empty array if there are no attachments.", + "example": [ + { + "content_type": "application/json", + "description": "An example description.", + "filename": "string", + "height": 1, + "id": "string", + "image_height": 1, + "image_source": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "image_url": "https://example.com", + "image_width": 1, + "key": "string", + "media_type": "application/json", + "name": "Example Name", + "object": {}, + "title": "Example Title", + "type": "file", + "url": "https://example.com", + "variants": [ + { + "content_type": "application/json", + "created_at": "2024-01-01T00:00:00Z", + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "filename": "string", + "height": 600, + "id": "mvr_0aBcDeFgHiJkLmNoPqRsTu", + "image_source": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "updated_at": "2024-01-01T00:00:00Z", + "url": "https://example.com", + "variant_key": "original", + "width": 800 + } + ], + "version": 1, + "width": 1 + } + ], + "items": { + "description": "A rich attachment associated with a message, such as a file, scraped link, artifact, task, media item, or inline action.", + "example": { + "content_type": "application/json", + "description": "An example description.", + "filename": "string", + "height": 1, + "id": "string", + "image_height": 1, + "image_source": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "image_url": "https://example.com", + "image_width": 1, + "key": "string", + "media_type": "application/json", + "name": "Example Name", + "object": {}, + "title": "Example Title", + "type": "file", + "url": "https://example.com", + "variants": [ + { + "content_type": "application/json", + "created_at": "2024-01-01T00:00:00Z", + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "filename": "string", + "height": 600, + "id": "mvr_0aBcDeFgHiJkLmNoPqRsTu", + "image_source": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "updated_at": "2024-01-01T00:00:00Z", + "url": "https://example.com", + "variant_key": "original", + "width": 800 + } + ], + "version": 1, + "width": 1 + }, + "properties": { + "content_type": { + "description": "MIME type of the attached file, e.g. `\"image/png\"` or `\"application/pdf\"`. Present on `file`, `artifact`, and `media` types. `null` otherwise.", + "example": "application/json", + "nullable": true, + "type": "string" + }, + "description": { + "description": "Short description. The page meta-description for `scraped_link`, the artifact description for `artifact`, and the task description for `task` types. `null` on other types.", + "example": "An example description.", + "nullable": true, + "type": "string" + }, + "filename": { + "description": "Original filename of the attached file, e.g. `\"report.pdf\"`. Present on `file`, `artifact`, and `media` types. `null` otherwise.", + "example": "string", + "nullable": true, + "type": "string" + }, + "height": { + "description": "Height in pixels of the media item. Present on `media` type only. `null` otherwise.", + "example": 1, + "nullable": true, + "type": "integer" + }, + "id": { + "description": "Unique identifier for this attachment within the message.", + "example": "string", + "type": "string" + }, + "image_height": { + "description": "Height in pixels of the scraped preview image. Present on `scraped_link` type only. `null` otherwise.", + "example": 1, + "nullable": true, + "type": "integer" + }, + "image_source": { + "description": "Image source metadata for inline rendering. Present on `file`, `scraped_link`, `artifact`, and `media` types when the content is an image. `null` otherwise.", + "example": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "nullable": true, + "properties": { + "file": { + "description": "ID of the underlying storage file (`fil_...`). `null` when the image is not backed by a platform storage file.", + "example": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "height": { + "description": "Height of the image in pixels. `null` if not known.", + "example": 600, + "nullable": true, + "type": "integer" + }, + "media": { + "description": "ID of the associated media record (`med_...`). `null` when the image is not linked to a media entity.", + "example": "med_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "mime_type": { + "description": "MIME type of the image, e.g. `\"image/png\"` or `\"image/jpeg\"`. `null` if not known.", + "example": "application/json", + "nullable": true, + "type": "string" + }, + "refresh_url": { + "description": "Endpoint URL you can call to obtain a fresh signed `url` when the current one has expired. `null` if the URL does not require refreshing.", + "example": "https://example.com", + "nullable": true, + "type": "string" + }, + "url": { + "description": "Signed or public URL for downloading the image. May be time-limited; use `refresh_url` to obtain a new URL when this one expires.", + "example": "https://example.com", + "nullable": true, + "type": "string" + }, + "width": { + "description": "Width of the image in pixels. `null` if not known.", + "example": 800, + "nullable": true, + "type": "integer" + } + }, + "type": "object" + }, + "image_url": { + "description": "URL of the preview image extracted from the scraped page. Present on `scraped_link` type only. `null` otherwise.", + "example": "https://example.com", + "nullable": true, + "type": "string" + }, + "image_width": { + "description": "Width in pixels of the scraped preview image. Present on `scraped_link` type only. `null` otherwise.", + "example": 1, + "nullable": true, + "type": "integer" + }, + "key": { + "description": "For `structured_data` type, what the data is about as set by the sender (for example `\"pr:14963\"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.", + "example": "string", + "nullable": true, + "type": "string" + }, + "media_type": { + "description": "The media category, e.g. `\"video\"` or `\"audio\"`. Present on `media` type only; omitted otherwise.", + "example": "application/json", + "type": "string" + }, + "name": { + "description": "Display name of the media item. Present on `media` type only. `null` otherwise.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "object": { + "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types.", + "example": {}, + "type": "object" + }, + "title": { + "description": "Display title. The page title for `scraped_link`, the artifact name for `artifact`, and the task title for `task` types. `null` on other types.", + "example": "Example Title", + "nullable": true, + "type": "string" + }, + "type": { + "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, `\"chart\"`, or `\"structured_data\"`. Determines which additional fields are present.", + "example": "file", + "type": "string" + }, + "url": { + "description": "URL to access the resource. A signed download URL for `file` and `artifact` types; the original URL for `scraped_link`; a media playback URL for `media`. `null` on `task` and `action` types.", + "example": "https://example.com", + "nullable": true, + "type": "string" + }, + "variants": { + "description": "Array of available encoding variants for the media item (e.g. different resolutions). Present on `media` type only; omitted otherwise.", + "example": [ + { + "content_type": "application/json", + "created_at": "2024-01-01T00:00:00Z", + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "filename": "string", + "height": 600, + "id": "mvr_0aBcDeFgHiJkLmNoPqRsTu", + "image_source": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "updated_at": "2024-01-01T00:00:00Z", + "url": "https://example.com", + "variant_key": "original", + "width": 800 + } + ], + "items": { + "description": "A processed variant of a media item, such as the original upload or a resized thumbnail, including a signed download URL resolved at request time.", + "example": { + "content_type": "application/json", + "created_at": "2024-01-01T00:00:00Z", + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "filename": "string", + "height": 600, + "id": "mvr_0aBcDeFgHiJkLmNoPqRsTu", + "image_source": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "updated_at": "2024-01-01T00:00:00Z", + "url": "https://example.com", + "variant_key": "original", + "width": 800 + }, + "properties": { + "content_type": { + "description": "MIME type of this variant's file (e.g., `\"image/jpeg\"`, `\"video/mp4\"`). `null` if the file is not loaded.", + "example": "application/json", + "nullable": true, + "type": "string" + }, + "created_at": { + "description": "When this variant was created (ISO 8601).", + "example": "2024-01-01T00:00:00Z", + "format": "date-time", + "type": "string" + }, + "file": { + "description": "ID of the underlying storage file that backs this variant (`fil_...`).", + "example": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "type": "string" + }, + "filename": { + "description": "Original filename of the uploaded file for this variant. `null` if the file is not loaded.", + "example": "string", + "nullable": true, + "type": "string" + }, + "height": { + "description": "Height of this variant in pixels. `null` if not recorded.", + "example": 600, + "nullable": true, + "type": "integer" + }, + "id": { + "description": "Media variant ID (`mvr_...`).", + "example": "mvr_0aBcDeFgHiJkLmNoPqRsTu", + "type": "string" + }, + "image_source": { + "description": "Resolved image delivery metadata for this variant, including dimensions and CDN URL. `null` for non-image content types.", + "example": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "nullable": true, + "properties": { + "file": { + "description": "ID of the underlying storage file (`fil_...`). `null` when the image is not backed by a platform storage file.", + "example": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "height": { + "description": "Height of the image in pixels. `null` if not known.", + "example": 600, + "nullable": true, + "type": "integer" + }, + "media": { + "description": "ID of the associated media record (`med_...`). `null` when the image is not linked to a media entity.", + "example": "med_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "mime_type": { + "description": "MIME type of the image, e.g. `\"image/png\"` or `\"image/jpeg\"`. `null` if not known.", + "example": "application/json", + "nullable": true, + "type": "string" + }, + "refresh_url": { + "description": "Endpoint URL you can call to obtain a fresh signed `url` when the current one has expired. `null` if the URL does not require refreshing.", + "example": "https://example.com", + "nullable": true, + "type": "string" + }, + "url": { + "description": "Signed or public URL for downloading the image. May be time-limited; use `refresh_url` to obtain a new URL when this one expires.", + "example": "https://example.com", + "nullable": true, + "type": "string" + }, + "width": { + "description": "Width of the image in pixels. `null` if not known.", + "example": 800, + "nullable": true, + "type": "integer" + } + }, + "type": "object" + }, + "updated_at": { + "description": "When this variant was last updated (ISO 8601).", + "example": "2024-01-01T00:00:00Z", + "format": "date-time", + "type": "string" + }, + "url": { + "description": "Signed download URL for this variant, resolved at request time. `null` if the file is unavailable.", + "example": "https://example.com", + "nullable": true, + "type": "string" + }, + "variant_key": { + "description": "Identifier for this variant's processing tier. Common values include `\"original\"` (the unmodified upload) and `\"thumbnail\"` (a resized preview).", + "example": "original", + "type": "string" + }, + "width": { + "description": "Width of this variant in pixels. `null` if not recorded.", + "example": 800, + "nullable": true, + "type": "integer" + } + }, + "required": [ + "id" + ], + "type": "object" + }, + "type": "array" + }, + "version": { + "description": "Version number of the attached artifact at the time of attachment. Present on `artifact` type only. `null` otherwise.", + "example": 1, + "nullable": true, + "type": "integer" + }, + "width": { + "description": "Width in pixels of the media item. Present on `media` type only. `null` otherwise.", + "example": 1, + "nullable": true, + "type": "integer" + } + }, + "required": [ + "id", + "type" + ], + "type": "object" + }, + "type": "array" + }, + "branched_thread": { + "description": "ID of the thread that was branched from this message (`thr_...`). `null` if this message has not spawned a branch thread.", + "example": "string", + "nullable": true, + "type": "string" + }, + "content": { + "description": "Text content of the message. `null` for messages that contain only attachments.", + "example": "Hello, how can I help you today?", + "nullable": true, + "type": "string" + }, + "context": { + "description": "Immutable structured context captured when the message was posted. Each entry has `type`, optional `title` and `content`, and scalar `attributes`. Always present; defaults to an empty array. Context is delivered to agents as escaped XML data, not as system instructions.", + "example": [ + { + "attributes": {}, + "content": "string", + "title": "PR #10458", + "type": "archdev.pull_request" + } + ], + "items": { + "description": "Structured context captured with a chat message and delivered to agents as data.", + "example": { + "attributes": {}, + "content": "string", + "title": "PR #10458", + "type": "archdev.pull_request" + }, + "properties": { + "attributes": { + "description": "Scalar key-value fields describing the context, such as route, repository, or pull-request number.", + "example": {}, + "type": "object" + }, + "content": { + "description": "Optional context body. The model receives it as escaped XML data, not a system instruction.", + "example": "string", + "nullable": true, + "type": "string" + }, + "title": { + "description": "Optional human-readable label for this context block.", + "example": "PR #10458", + "nullable": true, + "type": "string" + }, + "type": { + "description": "Stable context kind. Must start with a lowercase letter and contain only lowercase letters, numbers, dots, dashes, or underscores.", + "example": "archdev.pull_request", + "type": "string" + } + }, + "required": [ + "type" + ], + "type": "object" + }, + "type": "array" + }, + "created_at": { + "description": "When the message was posted (ISO 8601).", + "example": "string", + "type": "string" + }, + "has_replies": { + "description": "Whether this message has at least one reply. Only present when explicitly requested or computed by the server.", + "example": true, + "type": "boolean" + }, + "id": { + "description": "Message ID (`msg_...`).", + "example": "msg_0aBcDeFgHiJkLmNoPqRsTu", + "type": "string" + }, + "idempotency_key": { + "description": "Client-supplied idempotency key used to deduplicate message sends. `null` if the sender did not provide one.", + "example": "01234567-89ab-cdef-0123-456789abcdef", + "nullable": true, + "type": "string" + }, + "is_deleted": { + "description": "Whether this message is a deletion tombstone. `true` only on the `message_updated` broadcast emitted when a message is deleted: the original content is replaced with a placeholder and the message no longer exists on the server. Always `false` for live messages.", + "example": true, + "type": "boolean" + }, + "legacy_agent": { + "description": "Identifier of the legacy chat agent that sent this message, if applicable. `null` for messages sent by users or modern agent users.", + "example": "string", + "nullable": true, + "type": "string" + }, + "metadata": { + "description": "Arbitrary key-value metadata attached to the message. Always present; defaults to an empty object when no metadata has been set.", + "example": { + "key": "value" + }, + "type": "object" + }, + "org": { + "description": "ID of the organization that owns this message (`org_...`).", + "example": "org_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "reactions": { + "description": "Emoji and other reactions added to this message by users. Empty array if no reactions have been added or the association is not preloaded.", + "example": [ + { + "payload": { + "key": "value" + }, + "type": "emoji_reaction", + "user": "string" + } + ], + "items": { + "description": "A compact reaction record embedded in a message's `reactions` array, representing a single user's reaction to a message.", + "example": { + "payload": { + "key": "value" + }, + "type": "emoji_reaction", + "user": "string" + }, + "properties": { + "payload": { + "description": "Type-specific reaction data. For `\"emoji_reaction\"` reactions, contains an `emoji` key with the Unicode emoji string (e.g., `\"👍\"`).", + "example": { + "key": "value" + }, + "type": "object" + }, + "type": { + "description": "Reaction type identifier. Currently always `\"emoji_reaction\"` for emoji-based reactions.", + "example": "emoji_reaction", + "type": "string" + }, + "user": { + "description": "Public ID of the user who added the reaction (`usr_...`).", + "example": "string", + "type": "string" + } + }, + "required": [ + "type" + ], + "type": "object" + }, + "type": "array" + }, + "rendering_mode": { + "description": "Display hint for how the message should be rendered. One of `\"reply\"`, `\"direct\"`, or `\"inline\"`. `null` for user-authored messages, which are always rendered as standard replies.", + "example": "reply", + "nullable": true, + "type": "string" + }, + "replies": { + "description": "Inline array of reply messages, each serialized as a full message object. Only present when the server has preloaded replies for this message.", + "example": [ + {} + ], + "items": { + "type": "object" + }, + "type": "array" + }, + "replies_after_cursor": { + "description": "Opaque pagination cursor to fetch replies posted after the current page. Only present when inline replies are included in the response.", + "example": "string", + "nullable": true, + "type": "string" + }, + "replies_before_cursor": { + "description": "Opaque pagination cursor to fetch replies posted before the current page. Only present when inline replies are included in the response.", + "example": "string", + "nullable": true, + "type": "string" + }, + "reply_count": { + "description": "Total number of direct replies to this message. Only present when explicitly requested or computed by the server.", + "example": 1, + "type": "integer" + }, + "reply_to": { + "description": "The parent message this message is a reply to, expanded as a full message object when loaded. `null` if this is a top-level message or the association is not preloaded.", + "example": { + "acl": { + "add": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "grants": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "remove": [ + { + "principal": "string", + "principal_type": "user" + } + ] + }, + "actors": [ + { + "alias": "alice", + "id": "user-usr_01j3k5m7n9p2r4s6t8v0w1x2", + "name": "Example Name", + "profile_picture": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + } + } + ], + "agent": "agi_0aBcDeFgHiJkLmNoPqRsTu", + "agent_mode": "cli", + "attachments": [ + { + "content_type": "application/json", + "description": "An example description.", + "filename": "string", + "height": 1, + "id": "string", + "image_height": 1, + "image_source": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "image_url": "https://example.com", + "image_width": 1, + "key": "string", + "media_type": "application/json", + "name": "Example Name", + "object": {}, + "title": "Example Title", + "type": "file", + "url": "https://example.com", + "variants": [ + { + "content_type": "application/json", + "created_at": "2024-01-01T00:00:00Z", + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "filename": "string", + "height": 600, + "id": "mvr_0aBcDeFgHiJkLmNoPqRsTu", + "image_source": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "updated_at": "2024-01-01T00:00:00Z", + "url": "https://example.com", + "variant_key": "original", + "width": 800 + } + ], + "version": 1, + "width": 1 + } + ], + "branched_thread": "string", + "content": "Hello, how can I help you today?", + "context": [ + { + "attributes": {}, + "content": "string", + "title": "PR #10458", + "type": "archdev.pull_request" + } + ], + "created_at": "2024-01-01T00:00:00Z", + "has_replies": true, + "id": "msg_0aBcDeFgHiJkLmNoPqRsTu", + "idempotency_key": "01234567-89ab-cdef-0123-456789abcdef", + "is_deleted": true, + "legacy_agent": "string", + "metadata": { + "key": "value" + }, + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "reactions": [ + { + "payload": { + "key": "value" + }, + "type": "emoji_reaction", + "user": "string" + } + ], + "rendering_mode": "reply", + "replies": [ + {} + ], + "replies_after_cursor": "string", + "replies_before_cursor": "string", + "reply_count": 1, + "reply_to": {}, + "root_message_id": "string", + "sandbox": "string", + "team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "thread": "string", + "type": "note", + "user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "visibility": "default" + }, + "nullable": true, + "type": "object" + }, + "root_message_id": { + "description": "ID of the root message in this reply chain (`msg_...`). `null` for a top-level message. The value is persisted when the reply is created, so callers can correlate a multi-turn session without walking parent messages.", + "example": "string", + "nullable": true, + "type": "string" + }, + "sandbox": { + "description": "ID of the developer sandbox this message belongs to (`dsb_...`). `null` for non-sandbox messages.", + "example": "string", + "nullable": true, + "type": "string" + }, + "team": { + "description": "ID of the team this message is scoped to (`tem_...`). `null` if the message is not team-scoped.", + "example": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "thread": { + "description": "ID of the thread this message belongs to (`thr_...`).", + "example": "string", + "type": "string" + }, + "type": { + "description": "Optional client-defined classification for the message (for example `note` or `status`). Free-form string up to 64 characters. The value `system` is reserved for platform-authored messages and cannot be set by clients. `null` when unset.", + "example": "note", + "nullable": true, + "type": "string" + }, + "user": { + "description": "The human user who sent this message. Returns a public ID string (`usr_...`) when the association is not preloaded, or an expanded user object when it is. `null` for messages sent by agents.", + "example": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "oneOf": [ + { + "type": "string" + }, + { + "description": "A platform user account. Represents a human or system actor that can own threads, belong to an organization, and interact with the API.", + "example": { + "alias": "jdoe", + "app": "dap_0aBcDeFgHiJkLmNoPqRsTu", + "app_name": "Example Name", + "created_by_agent_user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_developer": "dva_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "email": "user@example.com", + "id": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "is_system_user": true, + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_name": "Example Name", + "org_role": "member", + "org_slug": "example-slug", + "sandbox": "dsb_0aBcDeFgHiJkLmNoPqRsTu", + "sandbox_name": "Example Name" + }, + "properties": { + "alias": { + "description": "Short handle or alias for the user. `null` if not set.", + "example": "jdoe", + "nullable": true, + "type": "string" + }, + "app": { + "description": "ID of the app this user (and their access token) is scoped to (`dap_...`). `null` if the user is not scoped to an app.", + "example": "dap_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "app_name": { + "description": "Display name of the user's app. `null` when the app association was not preloaded by the caller.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "created_by_agent_user": { + "description": "Agent user that created this account (`usr_...`). `null` unless an agent created it.", + "example": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "created_by_developer": { + "description": "Developer account that created this user (`dva_...`). `null` unless created via a developer token.", + "example": "dva_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "created_by_org": { + "description": "Org of the principal that created this user (`org_...`). `null` on legacy rows.", + "example": "org_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "created_by_team": { + "description": "Team that created this user (`tem_...`). `null` unless created as a team.", + "example": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "created_by_user": { + "description": "User who created this account (`usr_...`). `null` on self-signup or legacy rows.", + "example": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "email": { + "description": "Email address of the user.", + "example": "user@example.com", + "nullable": true, + "type": "string" + }, + "id": { + "description": "User ID (`usr_...`).", + "example": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "type": "string" + }, + "is_system_user": { + "description": "`true` if this account is an internal system user rather than a human. System users are created automatically by the platform.", + "example": true, + "type": "boolean" + }, + "metadata": { + "description": "Arbitrary key-value metadata attached to the user. Defaults to an empty object.", + "example": { + "key": "value" + }, + "type": "object" + }, + "name": { + "description": "Full display name of the user. `null` if the user has not set a name.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "org": { + "description": "ID of the organization this user belongs to (`org_...`). `null` if the user is not a member of any organization.", + "example": "org_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "org_name": { + "description": "Display name of the user's organization. `null` when the user is not in an org, or when the org association was not preloaded by the caller.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "org_role": { + "description": "Role of the user within their organization. One of `\"admin\"`, `\"member\"`, or `\"viewer\"`. `null` when the user is not a member of any organization.", + "example": "member", + "nullable": true, + "type": "string" + }, + "org_slug": { + "description": "Stable workspace slug for the user's organization. `null` when the user is not in an org, or when the org association was not preloaded by the caller.", + "example": "example-slug", + "nullable": true, + "type": "string" + }, + "sandbox": { + "description": "ID of the sandbox environment this user is scoped to (`sbx_...`). `null` for production users.", + "example": "dsb_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "sandbox_name": { + "description": "Display name of the user's sandbox environment. `null` for production users, or when the sandbox association was not preloaded by the caller.", + "example": "Example Name", + "nullable": true, + "type": "string" + } + }, + "required": [ + "id" + ], + "type": "object" + } + ] + }, + "visibility": { + "description": "Message-level visibility. `default` is visible to anyone who can see the parent thread. `private` is restricted to the sender and explicit ACL `read` grantees.", + "enum": [ + "default", + "private" + ], + "example": "default", + "type": "string" + } + }, + "required": [ + "id" + ], + "type": "object" + }, + "participant": { + "description": "Array of participant user IDs (`usr_...`) who are members of this thread.", + "example": [ + "string" + ], + "items": { + "type": "string" + }, + "type": "array" + }, + "participants": { + "description": "Expanded participant user objects for each member of this thread. Populated only when the association is loaded.", + "example": [ + { + "alias": "jdoe", + "app": "dap_0aBcDeFgHiJkLmNoPqRsTu", + "app_name": "Example Name", + "created_by_agent_user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_developer": "dva_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "email": "user@example.com", + "id": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "is_system_user": true, + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_name": "Example Name", + "org_role": "member", + "org_slug": "example-slug", + "sandbox": "dsb_0aBcDeFgHiJkLmNoPqRsTu", + "sandbox_name": "Example Name" + } + ], + "items": { + "description": "A platform user account. Represents a human or system actor that can own threads, belong to an organization, and interact with the API.", + "example": { + "alias": "jdoe", + "app": "dap_0aBcDeFgHiJkLmNoPqRsTu", + "app_name": "Example Name", + "created_by_agent_user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_developer": "dva_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "created_by_user": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "email": "user@example.com", + "id": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "is_system_user": true, + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_name": "Example Name", + "org_role": "member", + "org_slug": "example-slug", + "sandbox": "dsb_0aBcDeFgHiJkLmNoPqRsTu", + "sandbox_name": "Example Name" + }, + "properties": { + "alias": { + "description": "Short handle or alias for the user. `null` if not set.", + "example": "jdoe", + "nullable": true, + "type": "string" + }, + "app": { + "description": "ID of the app this user (and their access token) is scoped to (`dap_...`). `null` if the user is not scoped to an app.", + "example": "dap_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "app_name": { + "description": "Display name of the user's app. `null` when the app association was not preloaded by the caller.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "created_by_agent_user": { + "description": "Agent user that created this account (`usr_...`). `null` unless an agent created it.", + "example": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "created_by_developer": { + "description": "Developer account that created this user (`dva_...`). `null` unless created via a developer token.", + "example": "dva_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "created_by_org": { + "description": "Org of the principal that created this user (`org_...`). `null` on legacy rows.", + "example": "org_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "created_by_team": { + "description": "Team that created this user (`tem_...`). `null` unless created as a team.", + "example": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "created_by_user": { + "description": "User who created this account (`usr_...`). `null` on self-signup or legacy rows.", + "example": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "email": { + "description": "Email address of the user.", + "example": "user@example.com", + "nullable": true, + "type": "string" + }, + "id": { + "description": "User ID (`usr_...`).", + "example": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "type": "string" + }, + "is_system_user": { + "description": "`true` if this account is an internal system user rather than a human. System users are created automatically by the platform.", + "example": true, + "type": "boolean" + }, + "metadata": { + "description": "Arbitrary key-value metadata attached to the user. Defaults to an empty object.", + "example": { + "key": "value" + }, + "type": "object" + }, + "name": { + "description": "Full display name of the user. `null` if the user has not set a name.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "org": { + "description": "ID of the organization this user belongs to (`org_...`). `null` if the user is not a member of any organization.", + "example": "org_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "org_name": { + "description": "Display name of the user's organization. `null` when the user is not in an org, or when the org association was not preloaded by the caller.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "org_role": { + "description": "Role of the user within their organization. One of `\"admin\"`, `\"member\"`, or `\"viewer\"`. `null` when the user is not a member of any organization.", + "example": "member", + "nullable": true, + "type": "string" + }, + "org_slug": { + "description": "Stable workspace slug for the user's organization. `null` when the user is not in an org, or when the org association was not preloaded by the caller.", + "example": "example-slug", + "nullable": true, + "type": "string" + }, + "sandbox": { + "description": "ID of the sandbox environment this user is scoped to (`sbx_...`). `null` for production users.", + "example": "dsb_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "sandbox_name": { + "description": "Display name of the user's sandbox environment. `null` for production users, or when the sandbox association was not preloaded by the caller.", + "example": "Example Name", + "nullable": true, + "type": "string" + } + }, + "required": [ + "id" + ], + "type": "object" + }, + "type": "array" + }, + "participating_actor": { + "description": "Composite actor identifiers for all participants currently active in this thread. Present only when actor enrichment is requested.", + "example": [ + "string" + ], + "items": { + "type": "string" + }, + "type": "array" + }, + "participating_agents": { + "description": "Expanded agent objects for all agents participating in this thread. Present only when agent enrichment is requested.", + "example": [ + { + "acl": { + "add": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "grants": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "remove": [ + { + "principal": "string", + "principal_type": "user" + } + ] + }, + "app": "dap_0aBcDeFgHiJkLmNoPqRsTu", + "created_at": "2024-01-01T00:00:00Z", + "default_model": "claude-3-7-sonnet-latest", + "description": "An example description.", + "email": "user@example.com", + "id": "agi_0aBcDeFgHiJkLmNoPqRsTu", + "identity": "You are a helpful assistant that answers questions about ArchAstro products.", + "last_applied_template_config": "cfg_0aBcDeFgHiJkLmNoPqRsTu", + "lookup_key": "string", + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_name": "Example Name", + "originator": "deploy-pipeline", + "phone_number": "+15555550123", + "sandbox": "dsb_0aBcDeFgHiJkLmNoPqRsTu", + "source_solution": { + "current_solution": { + "category_keys": [ + "string" + ], + "created_at": "2024-01-01T00:00:00Z", + "description": "An example description.", + "events": {}, + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "image_url": "https://example.com", + "installed_config_ids": [ + "string" + ], + "kind": "Solution", + "latest_solution": "id_0aBcDeFgHiJkLmNoPqRsTu", + "latest_version": "1.0.0", + "lookup_key": "string", + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_logo": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "org_name": "Example Name", + "org_slug": "example-slug", + "owners": [ + "string" + ], + "readme_url": "https://example.com", + "screenshot_urls": [ + "https://example.com" + ], + "solution_id": "01234567-89ab-cdef-0123-456789abcdef", + "solution_version": "1.2.0", + "tag_keys": [ + "string" + ], + "template_kind": "AgentTemplate", + "templates": [ + { + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "AgentTemplate", + "lookup_key": "string", + "name": "Example Name", + "readme_url": "https://example.com", + "virtual_path": "string" + } + ], + "updated_at": "2024-01-01T00:00:00Z", + "upgrade_available": true, + "virtual_path": "string" + }, + "solution": { + "category_keys": [ + "string" + ], + "created_at": "2024-01-01T00:00:00Z", + "description": "An example description.", + "events": {}, + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "image_url": "https://example.com", + "installed_config_ids": [ + "string" + ], + "kind": "Solution", + "latest_solution": "id_0aBcDeFgHiJkLmNoPqRsTu", + "latest_version": "1.0.0", + "lookup_key": "string", + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_logo": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "org_name": "Example Name", + "org_slug": "example-slug", + "owners": [ + "string" + ], + "readme_url": "https://example.com", + "screenshot_urls": [ + "https://example.com" + ], + "solution_id": "01234567-89ab-cdef-0123-456789abcdef", + "solution_version": "1.2.0", + "tag_keys": [ + "string" + ], + "template_kind": "AgentTemplate", + "templates": [ + { + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "AgentTemplate", + "lookup_key": "string", + "name": "Example Name", + "readme_url": "https://example.com", + "virtual_path": "string" + } + ], + "updated_at": "2024-01-01T00:00:00Z", + "upgrade_available": true, + "virtual_path": "string" + }, + "template": { + "created_at": "2024-01-01T00:00:00Z", + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "agent_tool_template", + "lookup_key": "string", + "name": "Example Name", + "updated_at": "2024-01-01T00:00:00Z", + "virtual_path": "string" + } + }, + "team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "template_upgrade_available": true, + "updated_at": "2024-01-01T00:00:00Z", + "user": "usr_0aBcDeFgHiJkLmNoPqRsTu" + } + ], + "items": { + "description": "An AI agent that can be configured with tools, routines, and skills, and invoked to handle conversations or tasks.", + "example": { + "acl": { + "add": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "grants": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "remove": [ + { + "principal": "string", + "principal_type": "user" + } + ] + }, + "app": "dap_0aBcDeFgHiJkLmNoPqRsTu", + "created_at": "string", + "default_model": "claude-3-7-sonnet-latest", + "description": "An example description.", + "email": "user@example.com", + "id": "agi_0aBcDeFgHiJkLmNoPqRsTu", + "identity": "You are a helpful assistant that answers questions about ArchAstro products.", + "last_applied_template_config": "cfg_0aBcDeFgHiJkLmNoPqRsTu", + "lookup_key": "string", + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_name": "Example Name", + "originator": "deploy-pipeline", + "phone_number": "+15555550123", + "sandbox": "dsb_0aBcDeFgHiJkLmNoPqRsTu", + "source_solution": { + "current_solution": { + "category_keys": [ + "string" + ], + "created_at": "2024-01-01T00:00:00Z", + "description": "An example description.", + "events": {}, + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "image_url": "https://example.com", + "installed_config_ids": [ + "string" + ], + "kind": "Solution", + "latest_solution": "id_0aBcDeFgHiJkLmNoPqRsTu", + "latest_version": "1.0.0", + "lookup_key": "string", + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_logo": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "org_name": "Example Name", + "org_slug": "example-slug", + "owners": [ + "string" + ], + "readme_url": "https://example.com", + "screenshot_urls": [ + "https://example.com" + ], + "solution_id": "01234567-89ab-cdef-0123-456789abcdef", + "solution_version": "1.2.0", + "tag_keys": [ + "string" + ], + "template_kind": "AgentTemplate", + "templates": [ + { + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "AgentTemplate", + "lookup_key": "string", + "name": "Example Name", + "readme_url": "https://example.com", + "virtual_path": "string" + } + ], + "updated_at": "2024-01-01T00:00:00Z", + "upgrade_available": true, + "virtual_path": "string" + }, + "solution": { + "category_keys": [ + "string" + ], + "created_at": "2024-01-01T00:00:00Z", + "description": "An example description.", + "events": {}, + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "image_url": "https://example.com", + "installed_config_ids": [ + "string" + ], + "kind": "Solution", + "latest_solution": "id_0aBcDeFgHiJkLmNoPqRsTu", + "latest_version": "1.0.0", + "lookup_key": "string", + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_logo": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "org_name": "Example Name", + "org_slug": "example-slug", + "owners": [ + "string" + ], + "readme_url": "https://example.com", + "screenshot_urls": [ + "https://example.com" + ], + "solution_id": "01234567-89ab-cdef-0123-456789abcdef", + "solution_version": "1.2.0", + "tag_keys": [ + "string" + ], + "template_kind": "AgentTemplate", + "templates": [ + { + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "AgentTemplate", + "lookup_key": "string", + "name": "Example Name", + "readme_url": "https://example.com", + "virtual_path": "string" + } + ], + "updated_at": "2024-01-01T00:00:00Z", + "upgrade_available": true, + "virtual_path": "string" + }, + "template": { + "created_at": "2024-01-01T00:00:00Z", + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "agent_tool_template", + "lookup_key": "string", + "name": "Example Name", + "updated_at": "2024-01-01T00:00:00Z", + "virtual_path": "string" + } + }, + "team": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "template_upgrade_available": true, + "updated_at": "string", + "user": "usr_0aBcDeFgHiJkLmNoPqRsTu" + }, + "properties": { + "acl": { + "description": "Access control list for the agent. Contains a `grants` array where each entry specifies `principal_type`, `principal`, and `actions`. `null` when no ACL restrictions are applied and the agent is accessible to all members of its scope.", + "example": { + "add": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "grants": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "remove": [ + { + "principal": "string", + "principal_type": "user" + } + ] + }, + "nullable": true, + "properties": { + "add": { + "description": "Patch mode: grants to add or merge into the existing list. Cannot be combined with `grants`.", + "example": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "items": { + "description": "A single access-control grant that pairs a principal with the set of actions it is allowed to perform.", + "example": { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + }, + "properties": { + "actions": { + "description": "Array of action strings the principal is permitted to perform, e.g. `[\"read\", \"write\"]`. Must contain at least one entry.", + "example": [ + "read", + "write" + ], + "items": { + "type": "string" + }, + "type": "array" + }, + "principal": { + "description": "The identifier of the principal. A string ID for `\"user\"`, `\"team\"`, `\"org\"`, and `\"agent\"` types; one of `\"admin\"`, `\"member\"`, or `\"viewer\"` for `\"org_role\"`; omit entirely when `principal_type` is `\"everyone\"`.", + "example": "string", + "type": "string" + }, + "principal_type": { + "description": "The kind of principal receiving the grant. One of `\"user\"`, `\"team\"`, `\"org\"`, `\"org_role\"`, `\"agent\"`, or `\"everyone\"`.", + "example": "user", + "type": "string" + } + }, + "required": [ + "principal_type", + "actions" + ], + "type": "object" + }, + "type": "array" + }, + "grants": { + "description": "Replace mode: the complete new list of grants that replaces all existing entries. Send an empty array (`[]`) to clear all grants. Cannot be combined with `add` or `remove`.", + "example": [ + { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + } + ], + "items": { + "description": "A single access-control grant that pairs a principal with the set of actions it is allowed to perform.", + "example": { + "actions": [ + "read", + "write" + ], + "principal": "string", + "principal_type": "user" + }, + "properties": { + "actions": { + "description": "Array of action strings the principal is permitted to perform, e.g. `[\"read\", \"write\"]`. Must contain at least one entry.", + "example": [ + "read", + "write" + ], + "items": { + "type": "string" + }, + "type": "array" + }, + "principal": { + "description": "The identifier of the principal. A string ID for `\"user\"`, `\"team\"`, `\"org\"`, and `\"agent\"` types; one of `\"admin\"`, `\"member\"`, or `\"viewer\"` for `\"org_role\"`; omit entirely when `principal_type` is `\"everyone\"`.", + "example": "string", + "type": "string" + }, + "principal_type": { + "description": "The kind of principal receiving the grant. One of `\"user\"`, `\"team\"`, `\"org\"`, `\"org_role\"`, `\"agent\"`, or `\"everyone\"`.", + "example": "user", + "type": "string" + } + }, + "required": [ + "principal_type", + "actions" + ], + "type": "object" + }, + "type": "array" + }, + "remove": { + "description": "Patch mode: principals whose grants should be removed from the existing list. Cannot be combined with `grants`.", + "example": [ + { + "principal": "string", + "principal_type": "user" + } + ], + "items": { + "description": "Identifies a principal to be removed from an access-control list.", + "example": { + "principal": "string", + "principal_type": "user" + }, + "properties": { + "principal": { + "description": "The identifier of the principal to remove. A string ID for `\"user\"`, `\"team\"`, `\"org\"`, and `\"agent\"` types; one of `\"admin\"`, `\"member\"`, or `\"viewer\"` for `\"org_role\"`. Omit when `principal_type` is `\"everyone\"`.", + "example": "string", + "type": "string" + }, + "principal_type": { + "description": "The kind of principal to remove. One of `\"user\"`, `\"team\"`, `\"org\"`, `\"org_role\"`, `\"agent\"`, or `\"everyone\"`.", + "example": "user", + "type": "string" + } + }, + "required": [ + "principal_type" + ], + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "app": { + "description": "ID of the application that owns this agent (`dap_...`).", + "example": "dap_0aBcDeFgHiJkLmNoPqRsTu", + "type": "string" + }, + "created_at": { + "description": "When the agent was created (ISO 8601).", + "example": "string", + "type": "string" + }, + "default_model": { + "description": "Default LLM model identifier used by this agent when no model is specified at runtime (e.g. `\"claude-3-7-sonnet-latest\"`).", + "example": "claude-3-7-sonnet-latest", + "nullable": true, + "type": "string" + }, + "description": { + "description": "Human-readable description of what the agent does. `null` if not set.", + "example": "An example description.", + "nullable": true, + "type": "string" + }, + "email": { + "description": "Email address provisioned for this agent. `null` if email delivery is not configured.", + "example": "user@example.com", + "nullable": true, + "type": "string" + }, + "id": { + "description": "Agent ID (`agi_...`).", + "example": "agi_0aBcDeFgHiJkLmNoPqRsTu", + "type": "string" + }, + "identity": { + "description": "System-level identity prompt that shapes the agent's persona and behavior.", + "example": "You are a helpful assistant that answers questions about ArchAstro products.", + "nullable": true, + "type": "string" + }, + "last_applied_template_config": { + "description": "ID of the AgentTemplate config (`cfg_...`) this agent was last provisioned or updated from. `null` for manually created agents.", + "example": "cfg_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "lookup_key": { + "description": "Stable, user-defined identifier for this agent within the application. Unique per app.", + "example": "string", + "nullable": true, + "type": "string" + }, + "metadata": { + "description": "Arbitrary key-value metadata attached to the agent. Not interpreted by the platform.", + "example": { + "key": "value" + }, + "type": "object" + }, + "name": { + "description": "Human-readable display name for the agent. `null` if not set.", + "example": "Example Name", + "type": "string" + }, + "org": { + "description": "ID of the organization this agent belongs to (`org_...`). `null` if the agent is not org-scoped.", + "example": "org_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "org_name": { + "description": "Display name of the organization this agent belongs to. `null` when the agent is not org-scoped or when the org association was not preloaded.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "originator": { + "description": "Free-form label identifying the source or author that created this agent (e.g. a username or pipeline name).", + "example": "deploy-pipeline", + "nullable": true, + "type": "string" + }, + "phone_number": { + "description": "Phone number provisioned for this agent. `null` if SMS is not configured.", + "example": "+15555550123", + "nullable": true, + "type": "string" + }, + "sandbox": { + "description": "ID of the sandbox environment this agent is scoped to (`dsb_...`). `null` in production deployments.", + "example": "dsb_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "source_solution": { + "description": "Source Solution and AgentTemplate summary for agents provisioned from a Solution. Includes `upgrade_available`, `latest_version`, and `latest_solution` so you can render an upgrade badge without a separate dry-run call. `null` for hand-built agents and agents whose tracked template or parent Solution has been deleted. Populated only on single-agent GET responses, never on list endpoints.", + "example": { + "current_solution": { + "category_keys": [ + "string" + ], + "created_at": "2024-01-01T00:00:00Z", + "description": "An example description.", + "events": {}, + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "image_url": "https://example.com", + "installed_config_ids": [ + "string" + ], + "kind": "Solution", + "latest_solution": "id_0aBcDeFgHiJkLmNoPqRsTu", + "latest_version": "1.0.0", + "lookup_key": "string", + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_logo": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "org_name": "Example Name", + "org_slug": "example-slug", + "owners": [ + "string" + ], + "readme_url": "https://example.com", + "screenshot_urls": [ + "https://example.com" + ], + "solution_id": "01234567-89ab-cdef-0123-456789abcdef", + "solution_version": "1.2.0", + "tag_keys": [ + "string" + ], + "template_kind": "AgentTemplate", + "templates": [ + { + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "AgentTemplate", + "lookup_key": "string", + "name": "Example Name", + "readme_url": "https://example.com", + "virtual_path": "string" + } + ], + "updated_at": "2024-01-01T00:00:00Z", + "upgrade_available": true, + "virtual_path": "string" + }, + "solution": { + "category_keys": [ + "string" + ], + "created_at": "2024-01-01T00:00:00Z", + "description": "An example description.", + "events": {}, + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "image_url": "https://example.com", + "installed_config_ids": [ + "string" + ], + "kind": "Solution", + "latest_solution": "id_0aBcDeFgHiJkLmNoPqRsTu", + "latest_version": "1.0.0", + "lookup_key": "string", + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_logo": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "org_name": "Example Name", + "org_slug": "example-slug", + "owners": [ + "string" + ], + "readme_url": "https://example.com", + "screenshot_urls": [ + "https://example.com" + ], + "solution_id": "01234567-89ab-cdef-0123-456789abcdef", + "solution_version": "1.2.0", + "tag_keys": [ + "string" + ], + "template_kind": "AgentTemplate", + "templates": [ + { + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "AgentTemplate", + "lookup_key": "string", + "name": "Example Name", + "readme_url": "https://example.com", + "virtual_path": "string" + } + ], + "updated_at": "2024-01-01T00:00:00Z", + "upgrade_available": true, + "virtual_path": "string" + }, + "template": { + "created_at": "2024-01-01T00:00:00Z", + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "agent_tool_template", + "lookup_key": "string", + "name": "Example Name", + "updated_at": "2024-01-01T00:00:00Z", + "virtual_path": "string" + } + }, + "nullable": true, + "properties": { + "current_solution": { + "description": "Summary of the current parent Solution config row. `solution` is the pinned Solution version the agent points at; `current_solution` is the source Solution config row as it exists now.", + "example": { + "category_keys": [ + "string" + ], + "created_at": "2024-01-01T00:00:00Z", + "description": "An example description.", + "events": {}, + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "image_url": "https://example.com", + "installed_config_ids": [ + "string" + ], + "kind": "Solution", + "latest_solution": "id_0aBcDeFgHiJkLmNoPqRsTu", + "latest_version": "1.0.0", + "lookup_key": "string", + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_logo": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "org_name": "Example Name", + "org_slug": "example-slug", + "owners": [ + "string" + ], + "readme_url": "https://example.com", + "screenshot_urls": [ + "https://example.com" + ], + "solution_id": "01234567-89ab-cdef-0123-456789abcdef", + "solution_version": "1.2.0", + "tag_keys": [ + "string" + ], + "template_kind": "AgentTemplate", + "templates": [ + { + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "AgentTemplate", + "lookup_key": "string", + "name": "Example Name", + "readme_url": "https://example.com", + "virtual_path": "string" + } + ], + "updated_at": "2024-01-01T00:00:00Z", + "upgrade_available": true, + "virtual_path": "string" + }, + "properties": { + "category_keys": { + "description": "Category tag keys declared in the Solution body, used to group Solutions in the catalog. An empty array when the body declares none.", + "example": [ + "string" + ], + "items": { + "type": "string" + }, + "type": "array" + }, + "created_at": { + "description": "When the Solution config was first imported (ISO 8601).", + "example": "string", + "type": "string" + }, + "description": { + "description": "Short tagline or summary declared in the Solution body, used as the card subhead in catalog UIs. `null` when the Solution body does not set one.", + "example": "An example description.", + "nullable": true, + "type": "string" + }, + "events": { + "description": "Custom analytics events declared in the Solution body's `events:` manifest — a map of event key (snake_case) to its definition (`label`, optional `description`, optional typed `fields`). Dashboards use the `label` as the event's display name. Present as an empty object when the body declares none.", + "example": {}, + "type": "object" + }, + "id": { + "description": "Solution config ID (`cfg_...`).", + "example": "id_0aBcDeFgHiJkLmNoPqRsTu", + "type": "string" + }, + "image_url": { + "description": "Absolute URL of the Solution's cover image — the bundled asset the body's `image:` field names. A stable, non-expiring capability URL (like `org_logo.url`), safe to hold in caches and OpenGraph tags; it 404s if the Solution stops declaring a cover. `null` when the Solution has no cover image. Org-only rows remain `null`; when a list entry merges an org copy with its system counterpart, it may reuse the system row's public cover URL. Permanent URLs are never minted for private org assets.", + "example": "https://example.com", + "nullable": true, + "type": "string" + }, + "installed_config_ids": { + "description": "Config IDs (`cfg_...`) of this Solution's installations in the viewer's organization. The array is empty when the Solution is visible only from the system catalog.", + "example": [ + "string" + ], + "items": { + "type": "string" + }, + "type": "array" + }, + "kind": { + "description": "Resource type. Always `\"Solution\"`.", + "example": "Solution", + "type": "string" + }, + "latest_solution": { + "description": "When `upgrade_available` is `true`, the system-scope Solution config ID (`cfg_...`) that should be used as the upgrade source. `null` otherwise.", + "example": "id_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "latest_version": { + "description": "When `upgrade_available` is `true`, the higher system-scope `solution_version` available to upgrade to. `null` otherwise.", + "example": "1.0.0", + "nullable": true, + "type": "string" + }, + "lookup_key": { + "description": "The lookup key stored on the Solution config, if one was assigned during import. `null` when no lookup key was set.", + "example": "string", + "nullable": true, + "type": "string" + }, + "metadata": { + "description": "Arbitrary key-value metadata declared in the Solution body (e.g. category or display hints). Present as an empty object when the body declares none.", + "example": { + "key": "value" + }, + "type": "object" + }, + "name": { + "description": "Human-facing display name declared in the Solution body. `null` when the Solution body does not set one.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "org": { + "description": "Organization ID (`org_...`) that owns this Solution config, when the Solution is scoped to a specific org. `null` for system-scope (app-level) Solutions.", + "example": "org_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "org_logo": { + "description": "Canonical image-source object for the resolved `org`'s logo, used as the principal category section glyph. The `url` is a stable, non-expiring capability URL (`refresh_url` is `null` — there is nothing to refresh). `null` when `org_slug` is `null` or the org has no logo.", + "example": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "nullable": true, + "properties": { + "file": { + "description": "ID of the underlying storage file (`fil_...`). `null` when the image is not backed by a platform storage file.", + "example": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "height": { + "description": "Height of the image in pixels. `null` if not known.", + "example": 600, + "nullable": true, + "type": "integer" + }, + "media": { + "description": "ID of the associated media record (`med_...`). `null` when the image is not linked to a media entity.", + "example": "med_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "mime_type": { + "description": "MIME type of the image, e.g. `\"image/png\"` or `\"image/jpeg\"`. `null` if not known.", + "example": "application/json", + "nullable": true, + "type": "string" + }, + "refresh_url": { + "description": "Endpoint URL you can call to obtain a fresh signed `url` when the current one has expired. `null` if the URL does not require refreshing.", + "example": "https://example.com", + "nullable": true, + "type": "string" + }, + "url": { + "description": "Signed or public URL for downloading the image. May be time-limited; use `refresh_url` to obtain a new URL when this one expires.", + "example": "https://example.com", + "nullable": true, + "type": "string" + }, + "width": { + "description": "Width of the image in pixels. `null` if not known.", + "example": 800, + "nullable": true, + "type": "integer" + } + }, + "type": "object" + }, + "org_name": { + "description": "Display name of the resolved `org`. Pairs with `org_slug` as the principal catalog category's label. `null` when `org_slug` is `null`.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "org_slug": { + "description": "Resolved slug of the Solution body's `org` (the publishing organization), when set and it resolves to a real org visible to the viewer. When present this is the Solution's principal catalog category key — clients group the Solution under this org ahead of `category_keys`. `null` when the body has no `org` or it doesn't resolve.", + "example": "example-slug", + "nullable": true, + "type": "string" + }, + "owners": { + "description": "Owner scopes this Solution appears under. Members: `\"system\"` (app-level system scope) and/or `\"org\"` (viewer's org scope).", + "example": [ + "string" + ], + "items": { + "type": "string" + }, + "type": "array" + }, + "readme_url": { + "description": "Relative path to the public README endpoint with a signed token already embedded. `null` when the Solution has no README. Token expires in 1 hour — refresh via `GET /api/v1/solutions/:solution`.", + "example": "https://example.com", + "nullable": true, + "type": "string" + }, + "screenshot_urls": { + "description": "Absolute URLs of the Solution's gallery screenshots — the bundled assets the body's `screenshots:` field names, in declared order. Each is a stable, non-expiring capability URL with the same cacheability contract as `image_url` (one shared token, a `v` cache key, and a `file` param selecting the screenshot); a URL 404s if the Solution stops declaring its screenshot. An empty array when the Solution declares none, and always empty for org-scoped rows — the permanent URLs are minted for system-scope (catalog) Solutions only.", + "example": [ + "https://example.com" + ], + "items": { + "type": "string" + }, + "type": "array" + }, + "solution_id": { + "description": "Stable UUID declared in the Solution body, used to identify the same logical Solution across multiple installed copies and owner scopes. `null` when the body omits it.", + "example": "01234567-89ab-cdef-0123-456789abcdef", + "nullable": true, + "type": "string" + }, + "solution_version": { + "description": "Semver string declared in the Solution body (e.g. `\"1.2.0\"`). `null` when the body does not declare a version.", + "example": "1.2.0", + "nullable": true, + "type": "string" + }, + "tag_keys": { + "description": "Freeform tag keys declared in the Solution body. An empty array when the body declares none.", + "example": [ + "string" + ], + "items": { + "type": "string" + }, + "type": "array" + }, + "template_kind": { + "description": "Wrapped template kind — `\"AgentTemplate\"`, `\"AutomationTemplate\"`, `\"AgentRoutineTemplate\"`, `\"AgentToolTemplate\"`, `\"AgentComputerTemplate\"`, or `\"SolutionTemplateRef\"` for ref-mode bundles.", + "example": "AgentTemplate", + "nullable": true, + "type": "string" + }, + "templates": { + "description": "Template configs bundled by this Solution, in declaration order — the first entry is the deployable template the Solution wraps; the rest are sibling templates the wrapped template references.", + "example": [ + { + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "AgentTemplate", + "lookup_key": "string", + "name": "Example Name", + "readme_url": "https://example.com", + "virtual_path": "string" + } + ], + "items": { + "description": "Identity and display metadata for a single template bundled by a Solution, used to represent each wrapped or sibling template at template granularity.", + "example": { + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "AgentTemplate", + "lookup_key": "string", + "name": "Example Name", + "readme_url": "https://example.com", + "virtual_path": "string" + }, + "properties": { + "description": { + "description": "Short prose blurb from the template body's `description:` field. `null` when the body doesn't set one. Used as the card subhead in the Library carousel.", + "example": "An example description.", + "nullable": true, + "type": "string" + }, + "details": { + "description": "Template-kind-specific details selected by the `type` discriminator. `null` when this template kind has no additional details.", + "discriminator": { + "propertyName": "type" + }, + "nullable": true, + "oneOf": [ + { + "description": "AutomationTemplate-specific details exposed by a Solution template summary.", + "example": { + "automation_type": "string", + "invoke_contract": { + "input_schema": {}, + "participants": [ + { + "description": "An example description.", + "name": "reporter", + "required": true, + "type": "agent_user" + } + ], + "prefills": { + "participants": {}, + "payload": {} + } + }, + "type": "automation" + }, + "properties": { + "automation_type": { + "description": "Automation execution type (`invoked`, `scheduled`, or `trigger`). `null` when the template body does not declare one.", + "example": "string", + "nullable": true, + "type": "string" + }, + "invoke_contract": { + "description": "Schema-driven payload and participant inputs for an invoked automation. Used by installation clients to collect locked prefills before provisioning. `null` for non-invoked automation types.", + "example": { + "input_schema": {}, + "participants": [ + { + "description": "An example description.", + "name": "reporter", + "required": true, + "type": "agent_user" + } + ], + "prefills": { + "participants": {}, + "payload": {} + } + }, + "nullable": true, + "properties": { + "input_schema": { + "description": "JSON Schema validated against the whole invoke payload, from the automation's `input_schema_config`. `null` when none is configured.", + "example": {}, + "nullable": true, + "type": "object" + }, + "participants": { + "description": "Named participant slots declared by the workflow, sorted by name. `null` when the workflow declares none. Values supplied under the top-level `participants` field are agent IDs.", + "example": [ + { + "description": "An example description.", + "name": "reporter", + "required": true, + "type": "agent_user" + } + ], + "items": { + "description": "A named participant slot declared by an automation's workflow. Embedded stages hand work to the agent the invoker names for the slot.", + "example": { + "description": "An example description.", + "name": "reporter", + "required": true, + "type": "agent_user" + }, + "properties": { + "description": { + "description": "Workflow-authored explanation of the slot's role. `null` when the workflow declares none.", + "example": "An example description.", + "nullable": true, + "type": "string" + }, + "name": { + "description": "The slot's name, as referenced by the workflow. Supply the chosen agent under the top-level `participants[name]` field when invoking.", + "example": "reporter", + "type": "string" + }, + "required": { + "description": "Whether the workflow requires this slot to be filled for the run to complete its embedded stages.", + "example": true, + "type": "boolean" + }, + "type": { + "description": "The kind of principal the slot accepts. Currently always `\"agent_user\"` — the value supplied at invoke is an agent ID (`agi_...`).", + "example": "agent_user", + "type": "string" + } + }, + "required": [ + "name", + "type", + "required" + ], + "type": "object" + }, + "nullable": true, + "type": "array" + }, + "prefills": { + "description": "Owner-controlled payload and participant values the platform applies to every invocation. Supplying a conflicting value is rejected.", + "example": { + "participants": {}, + "payload": {} + }, + "properties": { + "participants": { + "description": "Participant slot-to-agent mappings applied by the platform. Caller values at these slots must match exactly.", + "example": {}, + "type": "object" + }, + "payload": { + "description": "Partial invocation payload applied by the platform. A caller may omit these values, but supplying a different value at any locked path is rejected.", + "example": {}, + "type": "object" + } + }, + "type": "object" + } + }, + "required": [ + "prefills" + ], + "type": "object" + }, + "type": { + "default": "automation", + "description": "Template-details discriminator. Always `automation` for this variant.", + "enum": [ + "automation" + ], + "example": "automation", + "type": "string" + } + }, + "required": [ + "type" + ], + "type": "object" + } + ] + }, + "display_name": { + "description": "Human-facing label from the template body's `display_name:` field. `null` when the body doesn't set one. Library carousels use this for the card title, falling back to a humanized `name`.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "id": { + "description": "Template config ID (`cfg_...`). `null` for inline-only templates.", + "example": "id_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "kind": { + "description": "Template config kind, or `SolutionTemplateRef` / `SolutionTemplatePath` when unresolved.", + "example": "AgentTemplate", + "type": "string" + }, + "lookup_key": { + "description": "Lookup key stamped on the template config at import time. `null` when no lookup key was assigned.", + "example": "string", + "nullable": true, + "type": "string" + }, + "name": { + "description": "Canonical name from the template body. For `AgentTemplate` this doubles as the human-facing label; for `AgentToolTemplate` it's the LLM-facing tool function identifier (snake_case); for `AgentRoutineTemplate` it's the routine identifier (kebab-case). Clients rendering carousels should prefer `display_name` and fall back to humanizing `name`.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "readme_url": { + "description": "Relative path to the public README endpoint with a signed token already embedded, scoped to this template's bundled markdown asset. `null` when the Solution body's `templates[].readme_path` is unset for this entry. Token expires in 1 hour — refresh via `GET /api/v1/solutions/:solution`.", + "example": "https://example.com", + "nullable": true, + "type": "string" + }, + "virtual_path": { + "description": "Stable virtual path assigned to the template config. `null` when no virtual path was set.", + "example": "string", + "nullable": true, + "type": "string" + } + }, + "required": [ + "kind" + ], + "type": "object" + }, + "type": "array" + }, + "updated_at": { + "description": "When the Solution config was last modified (ISO 8601).", + "example": "string", + "type": "string" + }, + "upgrade_available": { + "description": "`true` when this Solution is installed at the viewer's org scope and the app-level system scope carries a higher `solution_version`. Always `false` for system-only rows.", + "example": true, + "type": "boolean" + }, + "virtual_path": { + "description": "The stable virtual path assigned to this Solution config, used as the deduplication key when the same Solution appears under multiple owner scopes. `null` when unset.", + "example": "string", + "nullable": true, + "type": "string" + } + }, + "required": [ + "id", + "kind", + "templates", + "owners", + "installed_config_ids", + "upgrade_available" + ], + "type": "object" + }, + "solution": { + "description": "Summary of the parent Solution, including `upgrade_available`, `latest_version`, and `latest_solution` when a newer system-scoped version is available for the agent's org-scoped Solution.", + "example": { + "category_keys": [ + "string" + ], + "created_at": "2024-01-01T00:00:00Z", + "description": "An example description.", + "events": {}, + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "image_url": "https://example.com", + "installed_config_ids": [ + "string" + ], + "kind": "Solution", + "latest_solution": "id_0aBcDeFgHiJkLmNoPqRsTu", + "latest_version": "1.0.0", + "lookup_key": "string", + "metadata": { + "key": "value" + }, + "name": "Example Name", + "org": "org_0aBcDeFgHiJkLmNoPqRsTu", + "org_logo": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "org_name": "Example Name", + "org_slug": "example-slug", + "owners": [ + "string" + ], + "readme_url": "https://example.com", + "screenshot_urls": [ + "https://example.com" + ], + "solution_id": "01234567-89ab-cdef-0123-456789abcdef", + "solution_version": "1.2.0", + "tag_keys": [ + "string" + ], + "template_kind": "AgentTemplate", + "templates": [ + { + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "AgentTemplate", + "lookup_key": "string", + "name": "Example Name", + "readme_url": "https://example.com", + "virtual_path": "string" + } + ], + "updated_at": "2024-01-01T00:00:00Z", + "upgrade_available": true, + "virtual_path": "string" + }, + "properties": { + "category_keys": { + "description": "Category tag keys declared in the Solution body, used to group Solutions in the catalog. An empty array when the body declares none.", + "example": [ + "string" + ], + "items": { + "type": "string" + }, + "type": "array" + }, + "created_at": { + "description": "When the Solution config was first imported (ISO 8601).", + "example": "string", + "type": "string" + }, + "description": { + "description": "Short tagline or summary declared in the Solution body, used as the card subhead in catalog UIs. `null` when the Solution body does not set one.", + "example": "An example description.", + "nullable": true, + "type": "string" + }, + "events": { + "description": "Custom analytics events declared in the Solution body's `events:` manifest — a map of event key (snake_case) to its definition (`label`, optional `description`, optional typed `fields`). Dashboards use the `label` as the event's display name. Present as an empty object when the body declares none.", + "example": {}, + "type": "object" + }, + "id": { + "description": "Solution config ID (`cfg_...`).", + "example": "id_0aBcDeFgHiJkLmNoPqRsTu", + "type": "string" + }, + "image_url": { + "description": "Absolute URL of the Solution's cover image — the bundled asset the body's `image:` field names. A stable, non-expiring capability URL (like `org_logo.url`), safe to hold in caches and OpenGraph tags; it 404s if the Solution stops declaring a cover. `null` when the Solution has no cover image. Org-only rows remain `null`; when a list entry merges an org copy with its system counterpart, it may reuse the system row's public cover URL. Permanent URLs are never minted for private org assets.", + "example": "https://example.com", + "nullable": true, + "type": "string" + }, + "installed_config_ids": { + "description": "Config IDs (`cfg_...`) of this Solution's installations in the viewer's organization. The array is empty when the Solution is visible only from the system catalog.", + "example": [ + "string" + ], + "items": { + "type": "string" + }, + "type": "array" + }, + "kind": { + "description": "Resource type. Always `\"Solution\"`.", + "example": "Solution", + "type": "string" + }, + "latest_solution": { + "description": "When `upgrade_available` is `true`, the system-scope Solution config ID (`cfg_...`) that should be used as the upgrade source. `null` otherwise.", + "example": "id_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "latest_version": { + "description": "When `upgrade_available` is `true`, the higher system-scope `solution_version` available to upgrade to. `null` otherwise.", + "example": "1.0.0", + "nullable": true, + "type": "string" + }, + "lookup_key": { + "description": "The lookup key stored on the Solution config, if one was assigned during import. `null` when no lookup key was set.", + "example": "string", + "nullable": true, + "type": "string" + }, + "metadata": { + "description": "Arbitrary key-value metadata declared in the Solution body (e.g. category or display hints). Present as an empty object when the body declares none.", + "example": { + "key": "value" + }, + "type": "object" + }, + "name": { + "description": "Human-facing display name declared in the Solution body. `null` when the Solution body does not set one.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "org": { + "description": "Organization ID (`org_...`) that owns this Solution config, when the Solution is scoped to a specific org. `null` for system-scope (app-level) Solutions.", + "example": "org_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "org_logo": { + "description": "Canonical image-source object for the resolved `org`'s logo, used as the principal category section glyph. The `url` is a stable, non-expiring capability URL (`refresh_url` is `null` — there is nothing to refresh). `null` when `org_slug` is `null` or the org has no logo.", + "example": { + "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "height": 600, + "media": "med_0aBcDeFgHiJkLmNoPqRsTu", + "mime_type": "application/json", + "refresh_url": "https://example.com", + "url": "https://example.com", + "width": 800 + }, + "nullable": true, + "properties": { + "file": { + "description": "ID of the underlying storage file (`fil_...`). `null` when the image is not backed by a platform storage file.", + "example": "fil_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "height": { + "description": "Height of the image in pixels. `null` if not known.", + "example": 600, + "nullable": true, + "type": "integer" + }, + "media": { + "description": "ID of the associated media record (`med_...`). `null` when the image is not linked to a media entity.", + "example": "med_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "mime_type": { + "description": "MIME type of the image, e.g. `\"image/png\"` or `\"image/jpeg\"`. `null` if not known.", + "example": "application/json", + "nullable": true, + "type": "string" + }, + "refresh_url": { + "description": "Endpoint URL you can call to obtain a fresh signed `url` when the current one has expired. `null` if the URL does not require refreshing.", + "example": "https://example.com", + "nullable": true, + "type": "string" + }, + "url": { + "description": "Signed or public URL for downloading the image. May be time-limited; use `refresh_url` to obtain a new URL when this one expires.", + "example": "https://example.com", + "nullable": true, + "type": "string" + }, + "width": { + "description": "Width of the image in pixels. `null` if not known.", + "example": 800, + "nullable": true, + "type": "integer" + } + }, + "type": "object" + }, + "org_name": { + "description": "Display name of the resolved `org`. Pairs with `org_slug` as the principal catalog category's label. `null` when `org_slug` is `null`.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "org_slug": { + "description": "Resolved slug of the Solution body's `org` (the publishing organization), when set and it resolves to a real org visible to the viewer. When present this is the Solution's principal catalog category key — clients group the Solution under this org ahead of `category_keys`. `null` when the body has no `org` or it doesn't resolve.", + "example": "example-slug", + "nullable": true, + "type": "string" + }, + "owners": { + "description": "Owner scopes this Solution appears under. Members: `\"system\"` (app-level system scope) and/or `\"org\"` (viewer's org scope).", + "example": [ + "string" + ], + "items": { + "type": "string" + }, + "type": "array" + }, + "readme_url": { + "description": "Relative path to the public README endpoint with a signed token already embedded. `null` when the Solution has no README. Token expires in 1 hour — refresh via `GET /api/v1/solutions/:solution`.", + "example": "https://example.com", + "nullable": true, + "type": "string" + }, + "screenshot_urls": { + "description": "Absolute URLs of the Solution's gallery screenshots — the bundled assets the body's `screenshots:` field names, in declared order. Each is a stable, non-expiring capability URL with the same cacheability contract as `image_url` (one shared token, a `v` cache key, and a `file` param selecting the screenshot); a URL 404s if the Solution stops declaring its screenshot. An empty array when the Solution declares none, and always empty for org-scoped rows — the permanent URLs are minted for system-scope (catalog) Solutions only.", + "example": [ + "https://example.com" + ], + "items": { + "type": "string" + }, + "type": "array" + }, + "solution_id": { + "description": "Stable UUID declared in the Solution body, used to identify the same logical Solution across multiple installed copies and owner scopes. `null` when the body omits it.", + "example": "01234567-89ab-cdef-0123-456789abcdef", + "nullable": true, + "type": "string" + }, + "solution_version": { + "description": "Semver string declared in the Solution body (e.g. `\"1.2.0\"`). `null` when the body does not declare a version.", + "example": "1.2.0", + "nullable": true, + "type": "string" + }, + "tag_keys": { + "description": "Freeform tag keys declared in the Solution body. An empty array when the body declares none.", + "example": [ + "string" + ], + "items": { + "type": "string" + }, + "type": "array" + }, + "template_kind": { + "description": "Wrapped template kind — `\"AgentTemplate\"`, `\"AutomationTemplate\"`, `\"AgentRoutineTemplate\"`, `\"AgentToolTemplate\"`, `\"AgentComputerTemplate\"`, or `\"SolutionTemplateRef\"` for ref-mode bundles.", + "example": "AgentTemplate", + "nullable": true, + "type": "string" + }, + "templates": { + "description": "Template configs bundled by this Solution, in declaration order — the first entry is the deployable template the Solution wraps; the rest are sibling templates the wrapped template references.", + "example": [ + { + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "AgentTemplate", + "lookup_key": "string", + "name": "Example Name", + "readme_url": "https://example.com", + "virtual_path": "string" + } + ], + "items": { + "description": "Identity and display metadata for a single template bundled by a Solution, used to represent each wrapped or sibling template at template granularity.", + "example": { + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "AgentTemplate", + "lookup_key": "string", + "name": "Example Name", + "readme_url": "https://example.com", + "virtual_path": "string" + }, + "properties": { + "description": { + "description": "Short prose blurb from the template body's `description:` field. `null` when the body doesn't set one. Used as the card subhead in the Library carousel.", + "example": "An example description.", + "nullable": true, + "type": "string" + }, + "details": { + "description": "Template-kind-specific details selected by the `type` discriminator. `null` when this template kind has no additional details.", + "discriminator": { + "propertyName": "type" + }, + "nullable": true, + "oneOf": [ + { + "description": "AutomationTemplate-specific details exposed by a Solution template summary.", + "example": { + "automation_type": "string", + "invoke_contract": { + "input_schema": {}, + "participants": [ + { + "description": "An example description.", + "name": "reporter", + "required": true, + "type": "agent_user" + } + ], + "prefills": { + "participants": {}, + "payload": {} + } + }, + "type": "automation" + }, + "properties": { + "automation_type": { + "description": "Automation execution type (`invoked`, `scheduled`, or `trigger`). `null` when the template body does not declare one.", + "example": "string", + "nullable": true, + "type": "string" + }, + "invoke_contract": { + "description": "Schema-driven payload and participant inputs for an invoked automation. Used by installation clients to collect locked prefills before provisioning. `null` for non-invoked automation types.", + "example": { + "input_schema": {}, + "participants": [ + { + "description": "An example description.", + "name": "reporter", + "required": true, + "type": "agent_user" + } + ], + "prefills": { + "participants": {}, + "payload": {} + } + }, + "nullable": true, + "properties": { + "input_schema": { + "description": "JSON Schema validated against the whole invoke payload, from the automation's `input_schema_config`. `null` when none is configured.", + "example": {}, + "nullable": true, + "type": "object" + }, + "participants": { + "description": "Named participant slots declared by the workflow, sorted by name. `null` when the workflow declares none. Values supplied under the top-level `participants` field are agent IDs.", + "example": [ + { + "description": "An example description.", + "name": "reporter", + "required": true, + "type": "agent_user" + } + ], + "items": { + "description": "A named participant slot declared by an automation's workflow. Embedded stages hand work to the agent the invoker names for the slot.", + "example": { + "description": "An example description.", + "name": "reporter", + "required": true, + "type": "agent_user" + }, + "properties": { + "description": { + "description": "Workflow-authored explanation of the slot's role. `null` when the workflow declares none.", + "example": "An example description.", + "nullable": true, + "type": "string" + }, + "name": { + "description": "The slot's name, as referenced by the workflow. Supply the chosen agent under the top-level `participants[name]` field when invoking.", + "example": "reporter", + "type": "string" + }, + "required": { + "description": "Whether the workflow requires this slot to be filled for the run to complete its embedded stages.", + "example": true, + "type": "boolean" + }, + "type": { + "description": "The kind of principal the slot accepts. Currently always `\"agent_user\"` — the value supplied at invoke is an agent ID (`agi_...`).", + "example": "agent_user", + "type": "string" + } + }, + "required": [ + "name", + "type", + "required" + ], + "type": "object" + }, + "nullable": true, + "type": "array" + }, + "prefills": { + "description": "Owner-controlled payload and participant values the platform applies to every invocation. Supplying a conflicting value is rejected.", + "example": { + "participants": {}, + "payload": {} + }, + "properties": { + "participants": { + "description": "Participant slot-to-agent mappings applied by the platform. Caller values at these slots must match exactly.", + "example": {}, + "type": "object" + }, + "payload": { + "description": "Partial invocation payload applied by the platform. A caller may omit these values, but supplying a different value at any locked path is rejected.", + "example": {}, + "type": "object" + } + }, + "type": "object" + } + }, + "required": [ + "prefills" + ], + "type": "object" + }, + "type": { + "default": "automation", + "description": "Template-details discriminator. Always `automation` for this variant.", + "enum": [ + "automation" + ], + "example": "automation", + "type": "string" + } + }, + "required": [ + "type" + ], + "type": "object" + } + ] + }, + "display_name": { + "description": "Human-facing label from the template body's `display_name:` field. `null` when the body doesn't set one. Library carousels use this for the card title, falling back to a humanized `name`.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "id": { + "description": "Template config ID (`cfg_...`). `null` for inline-only templates.", + "example": "id_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "kind": { + "description": "Template config kind, or `SolutionTemplateRef` / `SolutionTemplatePath` when unresolved.", + "example": "AgentTemplate", + "type": "string" + }, + "lookup_key": { + "description": "Lookup key stamped on the template config at import time. `null` when no lookup key was assigned.", + "example": "string", + "nullable": true, + "type": "string" + }, + "name": { + "description": "Canonical name from the template body. For `AgentTemplate` this doubles as the human-facing label; for `AgentToolTemplate` it's the LLM-facing tool function identifier (snake_case); for `AgentRoutineTemplate` it's the routine identifier (kebab-case). Clients rendering carousels should prefer `display_name` and fall back to humanizing `name`.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "readme_url": { + "description": "Relative path to the public README endpoint with a signed token already embedded, scoped to this template's bundled markdown asset. `null` when the Solution body's `templates[].readme_path` is unset for this entry. Token expires in 1 hour — refresh via `GET /api/v1/solutions/:solution`.", + "example": "https://example.com", + "nullable": true, + "type": "string" + }, + "virtual_path": { + "description": "Stable virtual path assigned to the template config. `null` when no virtual path was set.", + "example": "string", + "nullable": true, + "type": "string" + } + }, + "required": [ + "kind" + ], + "type": "object" + }, + "type": "array" + }, + "updated_at": { + "description": "When the Solution config was last modified (ISO 8601).", + "example": "string", + "type": "string" + }, + "upgrade_available": { + "description": "`true` when this Solution is installed at the viewer's org scope and the app-level system scope carries a higher `solution_version`. Always `false` for system-only rows.", + "example": true, + "type": "boolean" + }, + "virtual_path": { + "description": "The stable virtual path assigned to this Solution config, used as the deduplication key when the same Solution appears under multiple owner scopes. `null` when unset.", + "example": "string", + "nullable": true, + "type": "string" + } + }, + "required": [ + "id", + "kind", + "templates", + "owners", + "installed_config_ids", + "upgrade_available" + ], + "type": "object" + }, + "template": { + "description": "Summary of the AgentTemplate config (`cfg_...`) the agent was last provisioned or updated from.", + "example": { + "created_at": "2024-01-01T00:00:00Z", + "description": "An example description.", + "display_name": "Example Name", + "id": "id_0aBcDeFgHiJkLmNoPqRsTu", + "kind": "agent_tool_template", + "lookup_key": "string", + "name": "Example Name", + "updated_at": "2024-01-01T00:00:00Z", + "virtual_path": "string" + }, + "properties": { + "created_at": { + "description": "When this template config was created (ISO 8601).", + "example": "2024-01-01T00:00:00Z", + "format": "date-time", + "type": "string" + }, + "description": { + "description": "Description of the template from the config body. `null` if the current version has no `description` field.", + "example": "An example description.", + "nullable": true, + "type": "string" + }, + "display_name": { + "description": "Human-readable display name from the config body. `null` if the current version has no `display_name` field.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "id": { + "description": "Template config ID (`cfg_...`).", + "example": "id_0aBcDeFgHiJkLmNoPqRsTu", + "type": "string" + }, + "kind": { + "description": "Config kind identifier for this template (e.g. `\"agent_tool_template\"`).", + "example": "agent_tool_template", + "type": "string" + }, + "lookup_key": { + "description": "Stable lookup key assigned to this template config. `null` if no lookup key is set.", + "example": "string", + "nullable": true, + "type": "string" + }, + "name": { + "description": "Template name as stored in the config body. `null` if the current version has no `name` field.", + "example": "Example Name", + "nullable": true, + "type": "string" + }, + "updated_at": { + "description": "When this template config was last modified (ISO 8601).", + "example": "2024-01-01T00:00:00Z", + "format": "date-time", + "type": "string" + }, + "virtual_path": { + "description": "Virtual filesystem path for this template config. `null` if not set.", + "example": "string", + "nullable": true, + "type": "string" + } + }, + "required": [ + "id", + "kind" + ], + "type": "object" + } + }, + "required": [ + "solution", + "template" + ], + "type": "object" + }, + "team": { + "description": "ID of the team that owns this agent (`tem_...`). `null` if the agent is not team-scoped.", + "example": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "template_upgrade_available": { + "description": "True when the agent's last-applied template version is behind the current version of its AgentTemplate config — i.e. reapplying the template (a per-agent upgrade) would bring it newer Solution content. Self-clears once the agent is reapplied. Computed on both the list endpoints and single-agent GET. Distinct from `source_solution.upgrade_available`, which compares Solution *versions*: an agent can lag its template (`template_upgrade_available: true`) while the org already holds the latest Solution version (`upgrade_available: false`).", + "example": true, + "nullable": true, + "type": "boolean" + }, + "updated_at": { + "description": "When the agent was last modified (ISO 8601).", + "example": "string", + "type": "string" + }, + "user": { + "description": "ID of the user that owns this agent (`usr_...`). `null` if the agent is not user-scoped.", + "example": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + } + }, + "required": [ + "id" + ], + "type": "object" + }, + "nullable": true, + "type": "array" + }, + "role": { + "description": "The authenticated user's membership role in this thread, e.g. `\"owner\"`, `\"member\"`, or `\"viewer\"`. `null` if the user is not a member.", + "example": "member", + "nullable": true, + "type": "string" + }, + "sandbox": { + "description": "ID of the developer sandbox this thread is scoped to (`dsb_...`). `null` for production threads.", + "example": "dsb_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, "type": "string" }, - "kind": { - "description": "Whether this is a company-domain org or a person-owned personal org.", - "enum": [ - "company", - "personal" + "settings": { + "description": "Per-thread configuration settings controlling AI agent behavior for this thread.", + "example": { + "agent_enabled": true + }, + "properties": { + "agent_enabled": { + "description": "Whether the AI agent is active for this thread. `true` enables AI responses; `false` disables them. Defaults to `true` when settings have not been explicitly configured. `null` when a client explicitly cleared the setting.", + "example": true, + "nullable": true, + "type": "boolean" + } + }, + "type": "object" + }, + "slug": { + "description": "URL-safe slug for the thread, used in human-readable permalinks. `null` if not assigned.", + "example": "example-slug", + "nullable": true, + "type": "string" + }, + "sub_threads": { + "description": "Threads that are nested under this thread as replies to a parent message. Present only when sub-thread enrichment is requested.", + "example": [ + {} ], - "example": "company", + "items": { + "type": "object" + }, + "nullable": true, + "type": "array" + }, + "tags": { + "description": "Status tags on the thread (e.g. `\"blocked\"`, `\"needs-review\"`). Edited by any thread participant via the `/threads/:thread/tags` endpoints and filterable on the thread list endpoints. Empty array if none set.", + "example": [ + "blocked", + "needs-review" + ], + "items": { + "type": "string" + }, + "type": "array" + }, + "team": { + "description": "ID of the team that owns this thread (`team_...`). `null` for user-owned or agent-owned threads.", + "example": "tem_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, "type": "string" }, - "name": { - "description": "Display name of the organization.", - "example": "Example Name", + "title": { + "description": "Human-readable name of the thread. `null` if no title has been set.", + "example": "Example Title", + "nullable": true, + "type": "string" + }, + "ttl": { + "description": "Offset-free expiry timestamp after which the thread may be automatically cleaned up. `null` if the thread does not expire.", + "example": "2026-08-15T12:00:00", + "nullable": true, + "type": "string" + }, + "unread_count": { + "description": "Number of messages in this thread that the authenticated user has not yet read. Present only when read-state enrichment is requested.", + "example": 5, + "nullable": true, + "type": "integer" + }, + "updated_at": { + "description": "When the thread was last modified (ISO 8601).", + "example": "string", + "type": "string" + }, + "user": { + "description": "ID of the user who owns this thread (`usr_...`). `null` for team-owned or agent-owned threads.", + "example": "usr_0aBcDeFgHiJkLmNoPqRsTu", + "nullable": true, + "type": "string" + }, + "visibility": { + "description": "Who can read the thread: `team` for every owning-team member, `restricted` for team-readable threads with an explicit roster, `private` for roster-only access, or `org` for every member of the owning organization.", + "enum": [ + "team", + "restricted", + "private", + "org" + ], + "example": "team", "type": "string" } }, "required": [ "id", - "name", - "kind" + "visibility" ], "type": "object" }, "type": "array" - }, - "has_next": { - "description": "`true` when a subsequent page exists; `false` on the last page.", - "example": true, - "type": "boolean" - }, - "has_prev": { - "description": "`true` when a previous page exists; `false` on the first page.", - "example": true, - "type": "boolean" - }, - "page": { - "description": "The current page number returned.", - "example": 1, - "type": "integer" - }, - "page_size": { - "description": "The number of results per page used for this response.", - "example": 1, - "type": "integer" - }, - "total_entries": { - "description": "Total number of organizations matching the query across all pages.", - "example": 1, - "type": "integer" - }, - "total_pages": { - "description": "Total number of pages for the current query and page size.", - "example": 1, - "type": "integer" } }, "required": [ @@ -46061,24 +52627,22 @@ "401": { "description": "Unauthorized" }, - "403": { - "description": "App-scoped token required. Use a token scoped to the target app." + "404": { + "description": "Organization not found" } }, - "summary": "Search organizations", + "summary": "List organization-visibility threads", "x-auth": [ "publishable_key", "bearer" ] - } - }, - "/api/v1/orgs/{org}/artifacts": { - "get": { - "description": "Returns completed system-owned organization snapshots, newest first. Private user, team, agent and thread artifacts are excluded.", - "operationId": "get_api_v1_orgs__org_artifacts", + }, + "post": { + "description": "Creates a thread owned by the organization rather than a team, user, or agent.\nEvery member of the organization can read and post without joining. The\nauthenticated caller must be an organization administrator, or use an\napp-scoped developer token for the organization's app.\n\nWhen `thread.key` is supplied, creation is idempotent: a second call with the\nsame key returns the existing org-visibility thread instead of inserting a\nduplicate.\n", + "operationId": "post_api_v1_orgs__org_threads", "parameters": [ { - "description": "Organization ID.", + "description": "Organization ID (`org_...`) that will own the created thread.", "example": "string", "in": "path", "name": "org", @@ -46086,348 +52650,251 @@ "schema": { "type": "string" } - }, - { - "description": "Maximum snapshots returned, from 1 to 100.", - "example": 1, - "in": "query", - "name": "limit", - "required": false, - "schema": { - "type": "integer" - } - }, - { - "description": "Opaque cursor for the next page of older snapshots.", - "example": "string", - "in": "query", - "name": "after_cursor", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Exact, case-sensitive grouping key.", - "example": "string", - "in": "query", - "name": "group_key", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Nonempty literal group prefix; mutually exclusive with group_key.", - "example": "string", - "in": "query", - "name": "group_key_prefix", - "required": false, - "schema": { - "type": "string" - } } ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "example": { - "after_cursor": "string", - "before_cursor": "string", - "data": [ + "requestBody": { + "content": { + "application/json": { + "schema": { + "example": { + "skip_welcome_message": true, + "thread": { + "create_legacy_agent": true, + "description": "An example description.", + "is_unlisted": true, + "key": "string", + "kind": "personal", + "members": [ { - "agent": "agt_0aBcDeFgHiJkLmNoPqRsTu", - "content_type": "application/json", - "created_at": "2024-01-01T00:00:00Z", - "current_version": "afv_0aBcDeFgHiJkLmNoPqRsTu", - "description": "An example description.", - "file": "string", - "file_name": "Example Name", - "file_url": "https://example.com", - "group_key": "string", - "id": "art_0aBcDeFgHiJkLmNoPqRsTu", - "image_source": { - "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", - "height": 600, - "media": "med_0aBcDeFgHiJkLmNoPqRsTu", - "mime_type": "application/json", - "refresh_url": "https://example.com", - "url": "https://example.com", - "width": 800 - }, - "name": "Example Name", - "org": "org_0aBcDeFgHiJkLmNoPqRsTu", - "sandbox": "string", - "system": true, - "team": "tem_0aBcDeFgHiJkLmNoPqRsTu", - "thread": "thr_0aBcDeFgHiJkLmNoPqRsTu", - "updated_at": "2024-01-01T00:00:00Z", - "user": "usr_0aBcDeFgHiJkLmNoPqRsTu", - "version": 1 + "id": "string", + "type": "user" } ], - "has_more": true - }, - "properties": { - "after_cursor": { - "example": "string", - "nullable": true, - "type": "string" + "metadata": { + "key": "value" }, - "before_cursor": { - "description": "Always null; pagination is forward-only.", - "example": "string", - "nullable": true, - "type": "string" + "muted": true, + "org_id": "string", + "profile_picture": { + "data": "string", + "filename": "string", + "mime_type": "application/json" }, - "data": { - "example": [ + "settings": { + "agent_enabled": true + }, + "slug": "example-slug", + "title": "Example Title", + "visibility": "team" + } + }, + "properties": { + "skip_welcome_message": { + "description": "When `true`, suppresses the automatic welcome message that is otherwise sent into the thread on creation. Defaults to `false`.", + "example": true, + "type": "boolean" + }, + "thread": { + "description": "Attributes for the new thread. Visibility is forced to `org`.", + "example": { + "create_legacy_agent": true, + "description": "An example description.", + "is_unlisted": true, + "key": "string", + "kind": "personal", + "members": [ { - "agent": "agt_0aBcDeFgHiJkLmNoPqRsTu", - "content_type": "application/json", - "created_at": "2024-01-01T00:00:00Z", - "current_version": "afv_0aBcDeFgHiJkLmNoPqRsTu", - "description": "An example description.", - "file": "string", - "file_name": "Example Name", - "file_url": "https://example.com", - "group_key": "string", - "id": "art_0aBcDeFgHiJkLmNoPqRsTu", - "image_source": { - "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", - "height": 600, - "media": "med_0aBcDeFgHiJkLmNoPqRsTu", - "mime_type": "application/json", - "refresh_url": "https://example.com", - "url": "https://example.com", - "width": 800 - }, - "name": "Example Name", - "org": "org_0aBcDeFgHiJkLmNoPqRsTu", - "sandbox": "string", - "system": true, - "team": "tem_0aBcDeFgHiJkLmNoPqRsTu", - "thread": "thr_0aBcDeFgHiJkLmNoPqRsTu", - "updated_at": "2024-01-01T00:00:00Z", - "user": "usr_0aBcDeFgHiJkLmNoPqRsTu", - "version": 1 + "id": "string", + "type": "user" } ], - "items": { - "description": "A versioned artifact produced or managed by an agent, such as a generated file, report, or code output.", - "example": { - "agent": "agt_0aBcDeFgHiJkLmNoPqRsTu", - "content_type": "application/json", - "created_at": "2024-01-01T00:00:00Z", - "current_version": "afv_0aBcDeFgHiJkLmNoPqRsTu", - "description": "An example description.", - "file": "string", - "file_name": "Example Name", - "file_url": "https://example.com", - "group_key": "string", - "id": "art_0aBcDeFgHiJkLmNoPqRsTu", - "image_source": { - "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", - "height": 600, - "media": "med_0aBcDeFgHiJkLmNoPqRsTu", - "mime_type": "application/json", - "refresh_url": "https://example.com", - "url": "https://example.com", - "width": 800 + "metadata": { + "key": "value" + }, + "muted": true, + "org_id": "string", + "profile_picture": { + "data": "string", + "filename": "string", + "mime_type": "application/json" + }, + "settings": { + "agent_enabled": true + }, + "slug": "example-slug", + "title": "Example Title", + "visibility": "team" + }, + "properties": { + "create_legacy_agent": { + "description": "When `true`, provisions a legacy chat agent alongside the thread. Only needed for integrations that depend on the pre-v2 agent model.", + "example": true, + "type": "boolean" + }, + "description": { + "description": "Optional longer description of the thread's purpose. `null` if not provided.", + "example": "An example description.", + "type": "string" + }, + "is_unlisted": { + "description": "When `true`, the thread is hidden from the default thread list and accessible only by direct link or ID.", + "example": true, + "type": "boolean" + }, + "key": { + "description": "Client-assigned unique key for idempotent creation or later lookup. Must be unique within the owning organization.", + "example": "string", + "type": "string" + }, + "kind": { + "description": "Optional behavioral subtype. `personal` is accepted only for a user-owned thread and limits membership to that user and agents currently owned by them. `feed` is accepted for any owner and renders the thread as a post feed: message lists return top-level posts with their newest replies inline, and agent responses attach to the root post. Mirror kinds remain server-derived and cannot be selected by callers.", + "enum": [ + "personal", + "feed" + ], + "example": "personal", + "type": "string" + }, + "members": { + "description": "Users and agents to add atomically when the thread is created. Each target must pass the same authorization rules as a post-creation member add. Slack mirror threads reject non-empty caller-supplied rosters because their membership is sync-owned.", + "example": [ + { + "id": "string", + "type": "user" + } + ], + "items": { + "description": "A user or agent to add atomically when the thread is created.", + "example": { + "id": "string", + "type": "user" }, - "name": "Example Name", - "org": "org_0aBcDeFgHiJkLmNoPqRsTu", - "sandbox": "string", - "system": true, - "team": "tem_0aBcDeFgHiJkLmNoPqRsTu", - "thread": "thr_0aBcDeFgHiJkLmNoPqRsTu", - "updated_at": "2024-01-01T00:00:00Z", - "user": "usr_0aBcDeFgHiJkLmNoPqRsTu", - "version": 1 + "properties": { + "id": { + "description": "Public user (`usr_...`) or agent (`agt_...`) ID matching `type`.", + "example": "string", + "type": "string" + }, + "type": { + "description": "Member kind. Use `user` for a user ID or `agent` for an agent ID.", + "enum": [ + "user", + "agent" + ], + "example": "user", + "type": "string" + } + }, + "required": [ + "type", + "id" + ], + "type": "object" + }, + "type": "array" + }, + "metadata": { + "description": "Arbitrary key-value pairs stored alongside the thread. Values must be strings or numbers.", + "example": { + "key": "value" + }, + "type": "object" + }, + "muted": { + "description": "When `true`, push and in-app notifications for this thread are suppressed for the creating user.", + "example": true, + "type": "boolean" + }, + "org_id": { + "description": "ID of the organization to create the thread under. Defaults to the authenticated user's primary organization when omitted.", + "example": "string", + "type": "string" + }, + "profile_picture": { + "description": "Optional profile image for the thread, provided as a base64-encoded payload.", + "example": { + "data": "string", + "filename": "string", + "mime_type": "application/json" }, "properties": { - "agent": { - "description": "ID of the agent that produced this artifact (`agt_...`). `null` if not agent-produced.", - "example": "agt_0aBcDeFgHiJkLmNoPqRsTu", - "type": "string" - }, - "content_type": { - "description": "MIME type of the current version's file, e.g. `\"text/csv\"` or `\"image/png\"`. `null` if no file is attached.", - "example": "application/json", - "type": "string" - }, - "created_at": { - "description": "When the artifact was first created (ISO 8601).", - "example": "2024-01-01T00:00:00Z", - "format": "date-time", - "type": "string" - }, - "current_version": { - "description": "ID of the current (latest published) artifact version (`artv_...`). `null` if no version has been published.", - "example": "afv_0aBcDeFgHiJkLmNoPqRsTu", - "type": "string" - }, - "description": { - "description": "Optional longer description of the artifact's contents or purpose. `null` if not set.", - "example": "An example description.", - "type": "string" - }, - "file": { - "description": "Storage file ID for the current version (`fil_...`). `null` if no file is attached.", + "data": { + "description": "Base64-encoded image bytes.", "example": "string", "type": "string" }, - "file_name": { - "description": "Original filename of the current version's file, e.g. `\"output.csv\"`. `null` if no file is attached.", - "example": "Example Name", - "type": "string" - }, - "file_url": { - "description": "Short-lived signed URL for downloading the current version's file. `null` if no file is attached.", - "example": "https://example.com", - "type": "string" - }, - "group_key": { - "description": "Optional nonunique, case-sensitive grouping key, limited to 1024 UTF-8 bytes. Null when unset; belongs to the artifact, not a content version.", + "filename": { + "description": "Original filename of the uploaded image, used for display and content-type inference.", "example": "string", - "nullable": true, - "type": "string" - }, - "id": { - "description": "Artifact ID (`art_...`).", - "example": "art_0aBcDeFgHiJkLmNoPqRsTu", - "type": "string" - }, - "image_source": { - "description": "Image source metadata for rendering the current version's file inline. Present only when `content_type` starts with `\"image/\"`. `null` otherwise.", - "example": { - "file": "fil_0aBcDeFgHiJkLmNoPqRsTu", - "height": 600, - "media": "med_0aBcDeFgHiJkLmNoPqRsTu", - "mime_type": "application/json", - "refresh_url": "https://example.com", - "url": "https://example.com", - "width": 800 - }, - "properties": { - "file": { - "description": "ID of the underlying storage file (`fil_...`). `null` when the image is not backed by a platform storage file.", - "example": "fil_0aBcDeFgHiJkLmNoPqRsTu", - "nullable": true, - "type": "string" - }, - "height": { - "description": "Height of the image in pixels. `null` if not known.", - "example": 600, - "nullable": true, - "type": "integer" - }, - "media": { - "description": "ID of the associated media record (`med_...`). `null` when the image is not linked to a media entity.", - "example": "med_0aBcDeFgHiJkLmNoPqRsTu", - "nullable": true, - "type": "string" - }, - "mime_type": { - "description": "MIME type of the image, e.g. `\"image/png\"` or `\"image/jpeg\"`. `null` if not known.", - "example": "application/json", - "nullable": true, - "type": "string" - }, - "refresh_url": { - "description": "Endpoint URL you can call to obtain a fresh signed `url` when the current one has expired. `null` if the URL does not require refreshing.", - "example": "https://example.com", - "nullable": true, - "type": "string" - }, - "url": { - "description": "Signed or public URL for downloading the image. May be time-limited; use `refresh_url` to obtain a new URL when this one expires.", - "example": "https://example.com", - "nullable": true, - "type": "string" - }, - "width": { - "description": "Width of the image in pixels. `null` if not known.", - "example": 800, - "nullable": true, - "type": "integer" - } - }, - "type": "object" - }, - "name": { - "description": "Human-readable name for the artifact, e.g. `\"Q2 Report\"`. `null` if not set.", - "example": "Example Name", - "type": "string" - }, - "org": { - "description": "ID of the organization this artifact belongs to (`org_...`).", - "example": "org_0aBcDeFgHiJkLmNoPqRsTu", "type": "string" }, - "sandbox": { - "description": "Identifier of the sandbox environment associated with this artifact. `null` if not sandbox-scoped.", - "example": "string", + "mime_type": { + "description": "MIME type of the image, e.g. `\"image/png\"` or `\"image/jpeg\"`.", + "example": "application/json", "type": "string" - }, - "system": { - "description": "True when the artifact has no user, team, or agent owner. An organization may own a system artifact.", + } + }, + "type": "object" + }, + "settings": { + "description": "Configuration overrides for the thread, such as AI model selection and context window settings.", + "example": { + "agent_enabled": true + }, + "properties": { + "agent_enabled": { + "description": "Whether the AI agent is active for this thread. `true` enables AI responses; `false` disables them. Defaults to `true` when settings have not been explicitly configured. `null` when a client explicitly cleared the setting.", "example": true, + "nullable": true, "type": "boolean" - }, - "team": { - "description": "ID of the team that owns this artifact (`tea_...`). `null` if not team-scoped.", - "example": "tem_0aBcDeFgHiJkLmNoPqRsTu", - "type": "string" - }, - "thread": { - "description": "ID of the thread in which this artifact was created (`thr_...`). `null` if not thread-scoped.", - "example": "thr_0aBcDeFgHiJkLmNoPqRsTu", - "type": "string" - }, - "updated_at": { - "description": "When the artifact record was last modified (ISO 8601).", - "example": "2024-01-01T00:00:00Z", - "format": "date-time", - "type": "string" - }, - "user": { - "description": "ID of the user who created this artifact (`usr_...`). `null` if not user-scoped.", - "example": "usr_0aBcDeFgHiJkLmNoPqRsTu", - "type": "string" - }, - "version": { - "description": "Current version number of the artifact. Increments each time a new version is published.", - "example": 1, - "type": "integer" } }, - "required": [ - "id" - ], "type": "object" }, - "type": "array" + "slug": { + "description": "Optional URL-safe identifier. Derived from the title when omitted and unique within the thread owner.", + "example": "example-slug", + "type": "string" + }, + "title": { + "description": "Display name for the thread. `null` if omitted, which causes the thread to be untitled.", + "example": "Example Title", + "type": "string" + }, + "visibility": { + "description": "Thread visibility. A team-owned thread with members must explicitly use `restricted` or `private`. User- and agent-owned threads with members default to `private` and reject every other value. `org` is only valid on an organization-owned thread with no team, user, or agent owner.", + "enum": [ + "team", + "restricted", + "private", + "org" + ], + "example": "team", + "type": "string" + } }, - "has_more": { - "example": true, - "type": "boolean" - } - }, - "required": [ - "data", - "has_more" - ], - "type": "object" + "type": "object" + } + }, + "required": [ + "thread" + ], + "type": "object" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Thread" } } }, - "description": "Successful response" - }, - "400": { - "description": "Invalid group filters; Invalid cursor" + "description": "The organization-visibility thread." }, "401": { "description": "Unauthorized" @@ -46437,9 +52904,12 @@ }, "404": { "description": "Organization not found" + }, + "422": { + "description": "Validation failed" } }, - "summary": "List completed organization artifacts", + "summary": "Create an organization-visibility thread", "x-auth": [ "publishable_key", "bearer" @@ -53892,6 +60362,7 @@ ] }, "post": { + "description": "Adds an indexed identity without changing the referenced object's ownership or ACL.\nFor private files, upload with POST /api/v1/files, then pass external_scope=platform,\nobject_type=file and object_id=fil_.... The reserved platform namespace means the\nauthenticated current backend/app/sandbox, not a hostname or stored URL.\n\nFile attachment requires both task mutation permission and current file read access.\nList and reverse lookup omit files that are missing or no longer readable, including\nthread-restricted files. Generic identities are not resolved as local files.\nGET /api/v1/files/:file rechecks permission and returns a fresh expiring download URL;\nnever persist that URL as the link identity. Existing signed URLs remain usable until\ntheir expiry. Task activity and replay may retain opaque file IDs, not file metadata,\nand confer no file access.\n\nRetain the upload response's file ID if attachment fails and retry the link request.\nDetaching or deleting a task does not delete the file. Deleting a file leaves historical\nlink events intact; replay does not restore bytes or access. No ACL grant is implicit.\nAgent-owned uploads use an authorized human session; agent-only file credentials\nremain unsupported.\n\nDownload URLs depend on the configured storage provider. The development local\nprovider returns a local URL prefix plus a storage path, but Platform does not\nserve that path over HTTP. Local-provider verification reads bytes from the\nrunning Platform's configured storage directory after authorized metadata reads;\nit does not prove HTTP download authorization. Serving local downloads through\nan authorization-preserving route is a separate follow-up, not a public /storage\nmount. Served providers are verified through their HTTP download URLs.\n", "operationId": "post_api_v1_tasks__task_links", "parameters": [ { @@ -57150,6 +63621,50 @@ ] } }, + "/api/v1/teams/{team}/dependents": { + "get": { + "description": "Returns the number of stored custom-object rows that deleting this Team will\nphysically delete. The count includes rows hidden after ordinary soft\ndeletion. This read-only preview does not delete or restore data.\n", + "operationId": "get_api_v1_teams__team_dependents", + "parameters": [ + { + "description": "Team ID (`team_...`) to inspect.", + "example": "string", + "in": "path", + "name": "team", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TeamDeleteImpactResponse" + } + } + }, + "description": "Stored custom-object rows and the existing physical-deletion contract." + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden - deletion permission or app scope required" + }, + "404": { + "description": "Team not found" + } + }, + "summary": "Preview Team deletion impact", + "x-auth": [ + "publishable_key", + "bearer" + ] + } + }, "/api/v1/teams/{team}/invite": { "post": { "description": "Generates a new invite code for the specified team. The authenticated user\nmust be a member of the team with the `owner` or `admin` role.\n\nThe returned code is a short alphanumeric string that other users can\npresent to join the team. Each call produces a new code; previously issued\ncodes are not invalidated by this request. Codes expire after seven days.\n\nSharing a code intentionally grants membership across organizations within\nthe same application, including access to objects shared with team members.\nTreat it as a bearer credential. Revoke an individual code with\nDELETE /api/v1/teams/:team/invite/:code before issuing a replacement.\nRevocation does not remove existing members or their access.\n", @@ -64845,6 +71360,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -65256,6 +71772,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -65664,6 +72181,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -66188,7 +72706,7 @@ "type": "string" }, "kind": { - "description": "Thread subtype: `\"standard\"` for ordinary threads, `\"personal\"` for a user-and-owned-agents roster, `\"slack_mirror\"` for the membership-strict mirror of a Slack channel, or `\"slashwork_mirror\"` for the membership-strict mirror of a Slashwork group. `personal` is an explicit user-thread creation option; mirror kinds are server-derived.", + "description": "Thread subtype: `\"standard\"` for ordinary threads, `\"personal\"` for a user-and-owned-agents roster, `\"feed\"` for a post feed with inline replies, `\"slack_mirror\"` for the membership-strict mirror of a Slack channel, or `\"slashwork_mirror\"` for the membership-strict mirror of a Slashwork group. `personal` and `feed` are explicit creation options; mirror kinds are server-derived.", "example": "string", "nullable": true, "type": "string" @@ -66298,6 +72816,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -66705,6 +73224,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -66758,6 +73278,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -66896,6 +73417,12 @@ "nullable": true, "type": "integer" }, + "key": { + "description": "For `structured_data` type, what the data is about as set by the sender (for example `\"pr:14963\"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.", + "example": "string", + "nullable": true, + "type": "string" + }, "media_type": { "description": "The media category, e.g. `\"video\"` or `\"audio\"`. Present on `media` type only; omitted otherwise.", "example": "application/json", @@ -66908,7 +73435,7 @@ "type": "string" }, "object": { - "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types.", + "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types.", "example": {}, "type": "object" }, @@ -66919,7 +73446,7 @@ "type": "string" }, "type": { - "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, or `\"chart\"`. Determines which additional fields are present.", + "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, `\"chart\"`, or `\"structured_data\"`. Determines which additional fields are present.", "example": "file", "type": "string" }, @@ -67375,6 +73902,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -69919,11 +76447,12 @@ "type": "string" }, "visibility": { - "description": "Who can read the thread: `team` for every owning-team member, `restricted` for team-readable threads with an explicit roster, or `private` for roster-only access.", + "description": "Who can read the thread: `team` for every owning-team member, `restricted` for team-readable threads with an explicit roster, `private` for roster-only access, or `org` for every member of the owning organization.", "enum": [ "team", "restricted", - "private" + "private", + "org" ], "example": "team", "type": "string" @@ -70070,9 +76599,10 @@ "type": "string" }, "kind": { - "description": "Optional behavioral subtype. `personal` is accepted only for a user-owned thread and limits membership to that user and agents currently owned by them. Mirror kinds remain server-derived and cannot be selected by callers.", + "description": "Optional behavioral subtype. `personal` is accepted only for a user-owned thread and limits membership to that user and agents currently owned by them. `feed` is accepted for any owner and renders the thread as a post feed: message lists return top-level posts with their newest replies inline, and agent responses attach to the root post. Mirror kinds remain server-derived and cannot be selected by callers.", "enum": [ - "personal" + "personal", + "feed" ], "example": "personal", "type": "string" @@ -70184,11 +76714,12 @@ "type": "string" }, "visibility": { - "description": "Thread visibility. A team-owned thread with members must explicitly use `restricted` or `private`. User- and agent-owned threads with members default to `private` and reject every other value.", + "description": "Thread visibility. A team-owned thread with members must explicitly use `restricted` or `private`. User- and agent-owned threads with members default to `private` and reject every other value. `org` is only valid on an organization-owned thread with no team, user, or agent owner.", "enum": [ "team", "restricted", - "private" + "private", + "org" ], "example": "team", "type": "string" @@ -72028,7 +78559,7 @@ }, "/api/v1/threads/{thread}/messages": { "get": { - "description": "Returns a cursor-paginated list of messages belonging to the specified thread,\nordered from oldest to newest. Supply `before_cursor`, `after_cursor`, or both\nto page through or bound the result set; omit both to receive the most recent page.\nSupply `anchor` and `direction` to fetch a window before, after, or around a\nspecific message. Use `anchor=last_matching&anchor_agent_mode=embedded` to\nresolve the anchor from the latest embedded-agent message, and add\n`anchor_agent` to scope that resolution to a single sender agent.\nSupply `metadata` as a JSON-encoded structured expression to filter message\nmetadata before cursor pagination or anchored window limits are applied.\n\nThe authenticated user must have access to the thread's owner (workspace or user).\nA 403 is returned if the thread exists but is not accessible to the caller; a 404\nis returned if the thread does not exist or is not visible to the authenticated user.\n\nPass `include_reply_counts: true` to annotate each message with the number of\nthreaded replies it has received. This adds a small amount of latency and should\nbe omitted when reply counts are not needed.\n", + "description": "Returns a cursor-paginated list of messages belonging to the specified thread,\nordered from oldest to newest. Supply `before_cursor`, `after_cursor`, or both\nto page through or bound the result set; omit both to receive the most recent page.\nSupply `anchor` and `direction` to fetch a window before, after, or around a\nspecific message. Use `anchor=last_matching&anchor_agent_mode=embedded` to\nresolve the anchor from the latest embedded-agent message, and add\n`anchor_agent` to scope that resolution to a single sender agent.\nSupply `metadata` as a JSON-encoded structured expression to filter message\nmetadata before cursor pagination or anchored window limits are applied.\n\nThe authenticated user must have access to the thread's owner (workspace or user).\nA 403 is returned if the thread exists but is not accessible to the caller; a 404\nis returned if the thread does not exist or is not visible to the authenticated user.\n\nThreads with `kind: feed` return only top-level posts, each with its newest\nreplies inline under `replies` and reply cursors for paging the rest.\n\nPass `include_reply_counts: true` to annotate each message with the number of\nthreaded replies it has received. This adds a small amount of latency and should\nbe omitted when reply counts are not needed.\n", "operationId": "get_api_v1_threads__thread_messages", "parameters": [ { @@ -72327,6 +78858,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -72482,6 +79014,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -72650,6 +79183,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -72797,6 +79331,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -72932,6 +79467,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -73346,6 +79882,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -73399,6 +79936,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -73537,6 +80075,12 @@ "nullable": true, "type": "integer" }, + "key": { + "description": "For `structured_data` type, what the data is about as set by the sender (for example `\"pr:14963\"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.", + "example": "string", + "nullable": true, + "type": "string" + }, "media_type": { "description": "The media category, e.g. `\"video\"` or `\"audio\"`. Present on `media` type only; omitted otherwise.", "example": "application/json", @@ -73549,7 +80093,7 @@ "type": "string" }, "object": { - "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types.", + "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types.", "example": {}, "type": "object" }, @@ -73560,7 +80104,7 @@ "type": "string" }, "type": { - "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, or `\"chart\"`. Determines which additional fields are present.", + "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, `\"chart\"`, or `\"structured_data\"`. Determines which additional fields are present.", "example": "file", "type": "string" }, @@ -74016,6 +80560,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -80686,6 +87231,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -81097,6 +87643,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -81505,6 +88052,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -82029,7 +88577,7 @@ "type": "string" }, "kind": { - "description": "Thread subtype: `\"standard\"` for ordinary threads, `\"personal\"` for a user-and-owned-agents roster, `\"slack_mirror\"` for the membership-strict mirror of a Slack channel, or `\"slashwork_mirror\"` for the membership-strict mirror of a Slashwork group. `personal` is an explicit user-thread creation option; mirror kinds are server-derived.", + "description": "Thread subtype: `\"standard\"` for ordinary threads, `\"personal\"` for a user-and-owned-agents roster, `\"feed\"` for a post feed with inline replies, `\"slack_mirror\"` for the membership-strict mirror of a Slack channel, or `\"slashwork_mirror\"` for the membership-strict mirror of a Slashwork group. `personal` and `feed` are explicit creation options; mirror kinds are server-derived.", "example": "string", "nullable": true, "type": "string" @@ -82139,6 +88687,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -82546,6 +89095,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -82599,6 +89149,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -82737,6 +89288,12 @@ "nullable": true, "type": "integer" }, + "key": { + "description": "For `structured_data` type, what the data is about as set by the sender (for example `\"pr:14963\"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.", + "example": "string", + "nullable": true, + "type": "string" + }, "media_type": { "description": "The media category, e.g. `\"video\"` or `\"audio\"`. Present on `media` type only; omitted otherwise.", "example": "application/json", @@ -82749,7 +89306,7 @@ "type": "string" }, "object": { - "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types.", + "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types.", "example": {}, "type": "object" }, @@ -82760,7 +89317,7 @@ "type": "string" }, "type": { - "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, or `\"chart\"`. Determines which additional fields are present.", + "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, `\"chart\"`, or `\"structured_data\"`. Determines which additional fields are present.", "example": "file", "type": "string" }, @@ -83216,6 +89773,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -85760,11 +92318,12 @@ "type": "string" }, "visibility": { - "description": "Who can read the thread: `team` for every owning-team member, `restricted` for team-readable threads with an explicit roster, or `private` for roster-only access.", + "description": "Who can read the thread: `team` for every owning-team member, `restricted` for team-readable threads with an explicit roster, `private` for roster-only access, or `org` for every member of the owning organization.", "enum": [ "team", "restricted", - "private" + "private", + "org" ], "example": "team", "type": "string" @@ -85911,9 +92470,10 @@ "type": "string" }, "kind": { - "description": "Optional behavioral subtype. `personal` is accepted only for a user-owned thread and limits membership to that user and agents currently owned by them. Mirror kinds remain server-derived and cannot be selected by callers.", + "description": "Optional behavioral subtype. `personal` is accepted only for a user-owned thread and limits membership to that user and agents currently owned by them. `feed` is accepted for any owner and renders the thread as a post feed: message lists return top-level posts with their newest replies inline, and agent responses attach to the root post. Mirror kinds remain server-derived and cannot be selected by callers.", "enum": [ - "personal" + "personal", + "feed" ], "example": "personal", "type": "string" @@ -86025,11 +92585,12 @@ "type": "string" }, "visibility": { - "description": "Thread visibility. A team-owned thread with members must explicitly use `restricted` or `private`. User- and agent-owned threads with members default to `private` and reject every other value.", + "description": "Thread visibility. A team-owned thread with members must explicitly use `restricted` or `private`. User- and agent-owned threads with members default to `private` and reject every other value. `org` is only valid on an organization-owned thread with no team, user, or agent owner.", "enum": [ "team", "restricted", - "private" + "private", + "org" ], "example": "team", "type": "string" @@ -89941,7 +96502,7 @@ ] }, { - "description": "Channel for real-time chat messaging.\n\nSupports team-scoped and user-scoped threads with keyed, transient, and direct\nthread access patterns.\n", + "description": "Channel for real-time chat messaging.\n\nSupports team-scoped and user-scoped threads with keyed, transient, and direct\nthread access patterns, plus org-scoped joins for organization-visibility\nthreads, where org membership alone grants read and post.\n", "joins": [ { "description": "Join a team-scoped thread by ID", @@ -90090,6 +96651,55 @@ "type": "object" } }, + { + "description": "Join an organization-visibility thread by ID", + "name": "join_org_thread", + "params": { + "example": { + "after_cursor": "string", + "before_cursor": "string", + "include_metadata": true, + "limit": 1, + "org_id": "string", + "thread_id": "string" + }, + "properties": { + "after_cursor": { + "example": "string", + "type": "string" + }, + "before_cursor": { + "example": "string", + "type": "string" + }, + "include_metadata": { + "example": true, + "type": "boolean" + }, + "limit": { + "example": 1, + "type": "integer" + }, + "org_id": { + "example": "string", + "type": "string" + }, + "thread_id": { + "example": "string", + "type": "string" + } + }, + "required": [ + "org_id", + "thread_id" + ], + "type": "object" + }, + "pattern": "api:chat:org:{org_id}:thread:{thread_id}", + "returns": { + "type": "object" + } + }, { "description": "Join a user-scoped thread by ID, optionally supplying local tools for a personal thread", "name": "join_user_thread", @@ -90802,6 +97412,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -91012,6 +97623,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -91462,6 +98074,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -92259,6 +98872,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -92469,6 +99083,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -97042,6 +103657,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -97189,6 +103805,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -97324,6 +103941,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -97738,6 +104356,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -97791,6 +104410,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -97929,6 +104549,12 @@ "nullable": true, "type": "integer" }, + "key": { + "description": "For `structured_data` type, what the data is about as set by the sender (for example `\"pr:14963\"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.", + "example": "string", + "nullable": true, + "type": "string" + }, "media_type": { "description": "The media category, e.g. `\"video\"` or `\"audio\"`. Present on `media` type only; omitted otherwise.", "example": "application/json", @@ -97941,7 +104567,7 @@ "type": "string" }, "object": { - "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types.", + "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types.", "example": {}, "type": "object" }, @@ -97952,7 +104578,7 @@ "type": "string" }, "type": { - "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, or `\"chart\"`. Determines which additional fields are present.", + "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, `\"chart\"`, or `\"structured_data\"`. Determines which additional fields are present.", "example": "file", "type": "string" }, @@ -98408,6 +105034,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -99080,6 +105707,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -99604,7 +106232,7 @@ "type": "string" }, "kind": { - "description": "Thread subtype: `\"standard\"` for ordinary threads, `\"personal\"` for a user-and-owned-agents roster, `\"slack_mirror\"` for the membership-strict mirror of a Slack channel, or `\"slashwork_mirror\"` for the membership-strict mirror of a Slashwork group. `personal` is an explicit user-thread creation option; mirror kinds are server-derived.", + "description": "Thread subtype: `\"standard\"` for ordinary threads, `\"personal\"` for a user-and-owned-agents roster, `\"feed\"` for a post feed with inline replies, `\"slack_mirror\"` for the membership-strict mirror of a Slack channel, or `\"slashwork_mirror\"` for the membership-strict mirror of a Slashwork group. `personal` and `feed` are explicit creation options; mirror kinds are server-derived.", "example": "string", "nullable": true, "type": "string" @@ -99714,6 +106342,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -100121,6 +106750,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -100174,6 +106804,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -100312,6 +106943,12 @@ "nullable": true, "type": "integer" }, + "key": { + "description": "For `structured_data` type, what the data is about as set by the sender (for example `\"pr:14963\"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.", + "example": "string", + "nullable": true, + "type": "string" + }, "media_type": { "description": "The media category, e.g. `\"video\"` or `\"audio\"`. Present on `media` type only; omitted otherwise.", "example": "application/json", @@ -100324,7 +106961,7 @@ "type": "string" }, "object": { - "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types.", + "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types.", "example": {}, "type": "object" }, @@ -100335,7 +106972,7 @@ "type": "string" }, "type": { - "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, or `\"chart\"`. Determines which additional fields are present.", + "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, `\"chart\"`, or `\"structured_data\"`. Determines which additional fields are present.", "example": "file", "type": "string" }, @@ -100791,6 +107428,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -103335,11 +109973,12 @@ "type": "string" }, "visibility": { - "description": "Who can read the thread: `team` for every owning-team member, `restricted` for team-readable threads with an explicit roster, or `private` for roster-only access.", + "description": "Who can read the thread: `team` for every owning-team member, `restricted` for team-readable threads with an explicit roster, `private` for roster-only access, or `org` for every member of the owning organization.", "enum": [ "team", "restricted", - "private" + "private", + "org" ], "example": "team", "type": "string" @@ -103745,6 +110384,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -104269,7 +110909,7 @@ "type": "string" }, "kind": { - "description": "Thread subtype: `\"standard\"` for ordinary threads, `\"personal\"` for a user-and-owned-agents roster, `\"slack_mirror\"` for the membership-strict mirror of a Slack channel, or `\"slashwork_mirror\"` for the membership-strict mirror of a Slashwork group. `personal` is an explicit user-thread creation option; mirror kinds are server-derived.", + "description": "Thread subtype: `\"standard\"` for ordinary threads, `\"personal\"` for a user-and-owned-agents roster, `\"feed\"` for a post feed with inline replies, `\"slack_mirror\"` for the membership-strict mirror of a Slack channel, or `\"slashwork_mirror\"` for the membership-strict mirror of a Slashwork group. `personal` and `feed` are explicit creation options; mirror kinds are server-derived.", "example": "string", "nullable": true, "type": "string" @@ -104379,6 +111019,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -104786,6 +111427,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -104839,6 +111481,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -104977,6 +111620,12 @@ "nullable": true, "type": "integer" }, + "key": { + "description": "For `structured_data` type, what the data is about as set by the sender (for example `\"pr:14963\"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.", + "example": "string", + "nullable": true, + "type": "string" + }, "media_type": { "description": "The media category, e.g. `\"video\"` or `\"audio\"`. Present on `media` type only; omitted otherwise.", "example": "application/json", @@ -104989,7 +111638,7 @@ "type": "string" }, "object": { - "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types.", + "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types.", "example": {}, "type": "object" }, @@ -105000,7 +111649,7 @@ "type": "string" }, "type": { - "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, or `\"chart\"`. Determines which additional fields are present.", + "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, `\"chart\"`, or `\"structured_data\"`. Determines which additional fields are present.", "example": "file", "type": "string" }, @@ -105456,6 +112105,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -108000,11 +114650,12 @@ "type": "string" }, "visibility": { - "description": "Who can read the thread: `team` for every owning-team member, `restricted` for team-readable threads with an explicit roster, or `private` for roster-only access.", + "description": "Who can read the thread: `team` for every owning-team member, `restricted` for team-readable threads with an explicit roster, `private` for roster-only access, or `org` for every member of the owning organization.", "enum": [ "team", "restricted", - "private" + "private", + "org" ], "example": "team", "type": "string" @@ -108136,6 +114787,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -108286,6 +114938,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -108433,6 +115086,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -108568,6 +115222,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -108982,6 +115637,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -109035,6 +115691,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -109173,6 +115830,12 @@ "nullable": true, "type": "integer" }, + "key": { + "description": "For `structured_data` type, what the data is about as set by the sender (for example `\"pr:14963\"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.", + "example": "string", + "nullable": true, + "type": "string" + }, "media_type": { "description": "The media category, e.g. `\"video\"` or `\"audio\"`. Present on `media` type only; omitted otherwise.", "example": "application/json", @@ -109185,7 +115848,7 @@ "type": "string" }, "object": { - "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types.", + "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types.", "example": {}, "type": "object" }, @@ -109196,7 +115859,7 @@ "type": "string" }, "type": { - "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, or `\"chart\"`. Determines which additional fields are present.", + "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, `\"chart\"`, or `\"structured_data\"`. Determines which additional fields are present.", "example": "file", "type": "string" }, @@ -109652,6 +116315,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -110448,6 +117112,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -110658,6 +117323,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -111456,6 +118122,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -111666,6 +118333,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -116239,6 +122907,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -116386,6 +123055,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -116521,6 +123191,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -116935,6 +123606,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -116988,6 +123660,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -117126,6 +123799,12 @@ "nullable": true, "type": "integer" }, + "key": { + "description": "For `structured_data` type, what the data is about as set by the sender (for example `\"pr:14963\"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.", + "example": "string", + "nullable": true, + "type": "string" + }, "media_type": { "description": "The media category, e.g. `\"video\"` or `\"audio\"`. Present on `media` type only; omitted otherwise.", "example": "application/json", @@ -117138,7 +123817,7 @@ "type": "string" }, "object": { - "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types.", + "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types.", "example": {}, "type": "object" }, @@ -117149,7 +123828,7 @@ "type": "string" }, "type": { - "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, or `\"chart\"`. Determines which additional fields are present.", + "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, `\"chart\"`, or `\"structured_data\"`. Determines which additional fields are present.", "example": "file", "type": "string" }, @@ -117605,6 +124284,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -118277,6 +124957,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -118801,7 +125482,7 @@ "type": "string" }, "kind": { - "description": "Thread subtype: `\"standard\"` for ordinary threads, `\"personal\"` for a user-and-owned-agents roster, `\"slack_mirror\"` for the membership-strict mirror of a Slack channel, or `\"slashwork_mirror\"` for the membership-strict mirror of a Slashwork group. `personal` is an explicit user-thread creation option; mirror kinds are server-derived.", + "description": "Thread subtype: `\"standard\"` for ordinary threads, `\"personal\"` for a user-and-owned-agents roster, `\"feed\"` for a post feed with inline replies, `\"slack_mirror\"` for the membership-strict mirror of a Slack channel, or `\"slashwork_mirror\"` for the membership-strict mirror of a Slashwork group. `personal` and `feed` are explicit creation options; mirror kinds are server-derived.", "example": "string", "nullable": true, "type": "string" @@ -118911,6 +125592,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -119318,6 +126000,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -119371,6 +126054,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -119509,6 +126193,12 @@ "nullable": true, "type": "integer" }, + "key": { + "description": "For `structured_data` type, what the data is about as set by the sender (for example `\"pr:14963\"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.", + "example": "string", + "nullable": true, + "type": "string" + }, "media_type": { "description": "The media category, e.g. `\"video\"` or `\"audio\"`. Present on `media` type only; omitted otherwise.", "example": "application/json", @@ -119521,7 +126211,7 @@ "type": "string" }, "object": { - "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types.", + "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types.", "example": {}, "type": "object" }, @@ -119532,7 +126222,7 @@ "type": "string" }, "type": { - "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, or `\"chart\"`. Determines which additional fields are present.", + "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, `\"chart\"`, or `\"structured_data\"`. Determines which additional fields are present.", "example": "file", "type": "string" }, @@ -119988,6 +126678,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -122532,11 +129223,12 @@ "type": "string" }, "visibility": { - "description": "Who can read the thread: `team` for every owning-team member, `restricted` for team-readable threads with an explicit roster, or `private` for roster-only access.", + "description": "Who can read the thread: `team` for every owning-team member, `restricted` for team-readable threads with an explicit roster, `private` for roster-only access, or `org` for every member of the owning organization.", "enum": [ "team", "restricted", - "private" + "private", + "org" ], "example": "team", "type": "string" @@ -122729,6 +129421,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -122877,6 +129570,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -123283,6 +129977,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -123336,6 +130031,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -123474,6 +130170,12 @@ "nullable": true, "type": "integer" }, + "key": { + "description": "For `structured_data` type, what the data is about as set by the sender (for example `\"pr:14963\"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.", + "example": "string", + "nullable": true, + "type": "string" + }, "media_type": { "description": "The media category, e.g. `\"video\"` or `\"audio\"`. Present on `media` type only; omitted otherwise.", "example": "application/json", @@ -123486,7 +130188,7 @@ "type": "string" }, "object": { - "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types.", + "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types.", "example": {}, "type": "object" }, @@ -123497,7 +130199,7 @@ "type": "string" }, "type": { - "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, or `\"chart\"`. Determines which additional fields are present.", + "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, `\"chart\"`, or `\"structured_data\"`. Determines which additional fields are present.", "example": "file", "type": "string" }, @@ -123953,6 +130655,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -124390,6 +131093,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -124538,6 +131242,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -124944,6 +131649,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -124997,6 +131703,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -125135,6 +131842,12 @@ "nullable": true, "type": "integer" }, + "key": { + "description": "For `structured_data` type, what the data is about as set by the sender (for example `\"pr:14963\"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.", + "example": "string", + "nullable": true, + "type": "string" + }, "media_type": { "description": "The media category, e.g. `\"video\"` or `\"audio\"`. Present on `media` type only; omitted otherwise.", "example": "application/json", @@ -125147,7 +131860,7 @@ "type": "string" }, "object": { - "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types.", + "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types.", "example": {}, "type": "object" }, @@ -125158,7 +131871,7 @@ "type": "string" }, "type": { - "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, or `\"chart\"`. Determines which additional fields are present.", + "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, `\"chart\"`, or `\"structured_data\"`. Determines which additional fields are present.", "example": "file", "type": "string" }, @@ -125614,6 +132327,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -126391,6 +133105,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -126548,6 +133263,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -126954,6 +133670,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -127007,6 +133724,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -127145,6 +133863,12 @@ "nullable": true, "type": "integer" }, + "key": { + "description": "For `structured_data` type, what the data is about as set by the sender (for example `\"pr:14963\"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.", + "example": "string", + "nullable": true, + "type": "string" + }, "media_type": { "description": "The media category, e.g. `\"video\"` or `\"audio\"`. Present on `media` type only; omitted otherwise.", "example": "application/json", @@ -127157,7 +133881,7 @@ "type": "string" }, "object": { - "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types.", + "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types.", "example": {}, "type": "object" }, @@ -127168,7 +133892,7 @@ "type": "string" }, "type": { - "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, or `\"chart\"`. Determines which additional fields are present.", + "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, `\"chart\"`, or `\"structured_data\"`. Determines which additional fields are present.", "example": "file", "type": "string" }, @@ -127624,6 +134348,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -127983,6 +134708,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -128132,6 +134858,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -128538,6 +135265,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -128591,6 +135319,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, @@ -128729,6 +135458,12 @@ "nullable": true, "type": "integer" }, + "key": { + "description": "For `structured_data` type, what the data is about as set by the sender (for example `\"pr:14963\"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.", + "example": "string", + "nullable": true, + "type": "string" + }, "media_type": { "description": "The media category, e.g. `\"video\"` or `\"audio\"`. Present on `media` type only; omitted otherwise.", "example": "application/json", @@ -128741,7 +135476,7 @@ "type": "string" }, "object": { - "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types.", + "description": "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types.", "example": {}, "type": "object" }, @@ -128752,7 +135487,7 @@ "type": "string" }, "type": { - "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, or `\"chart\"`. Determines which additional fields are present.", + "description": "The attachment type. One of `\"file\"`, `\"scraped_link\"`, `\"artifact\"`, `\"task\"`, `\"media\"`, `\"action\"`, `\"chart\"`, or `\"structured_data\"`. Determines which additional fields are present.", "example": "file", "type": "string" }, @@ -129208,6 +135943,7 @@ }, "image_url": "https://example.com", "image_width": 1, + "key": "string", "media_type": "application/json", "name": "Example Name", "object": {}, diff --git a/src/archastro/platform/channels/api_chat_channel.py b/src/archastro/platform/channels/api_chat_channel.py index fb937f5..5c16557 100644 --- a/src/archastro/platform/channels/api_chat_channel.py +++ b/src/archastro/platform/channels/api_chat_channel.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: 516661809198 +# Content hash: 6cff96f782bb from collections.abc import Callable from datetime import datetime @@ -275,16 +275,18 @@ class MessageAddedPayloadMessageAttachmentsItem(TypedDict, total=False): "URL of the preview image extracted from the scraped page. Present on `scraped_link` type only. `null` otherwise." image_width: int | None "Width in pixels of the scraped preview image. Present on `scraped_link` type only. `null` otherwise." + key: str | None + 'For `structured_data` type, what the data is about as set by the sender (for example `"pr:14963"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.' media_type: str | None 'The media category, e.g. `"video"` or `"audio"`. Present on `media` type only; omitted otherwise.' name: str | None "Display name of the media item. Present on `media` type only. `null` otherwise." object: dict[str, Any] | None - "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types." + "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types." title: str | None "Display title. The page title for `scraped_link`, the artifact name for `artifact`, and the task title for `task` types. `null` on other types." type: Required[str] - 'The attachment type. One of `"file"`, `"scraped_link"`, `"artifact"`, `"task"`, `"media"`, `"action"`, or `"chart"`. Determines which additional fields are present.' + 'The attachment type. One of `"file"`, `"scraped_link"`, `"artifact"`, `"task"`, `"media"`, `"action"`, `"chart"`, or `"structured_data"`. Determines which additional fields are present.' url: str | None "URL to access the resource. A signed download URL for `file` and `artifact` types; the original URL for `scraped_link`; a media playback URL for `media`. `null` on `task` and `action` types." variants: list[MessageAddedPayloadMessageAttachmentsItemVariantsItem] | None @@ -528,16 +530,18 @@ class MessageUpdatedPayloadMessageAttachmentsItem(TypedDict, total=False): "URL of the preview image extracted from the scraped page. Present on `scraped_link` type only. `null` otherwise." image_width: int | None "Width in pixels of the scraped preview image. Present on `scraped_link` type only. `null` otherwise." + key: str | None + 'For `structured_data` type, what the data is about as set by the sender (for example `"pr:14963"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.' media_type: str | None 'The media category, e.g. `"video"` or `"audio"`. Present on `media` type only; omitted otherwise.' name: str | None "Display name of the media item. Present on `media` type only. `null` otherwise." object: dict[str, Any] | None - "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types." + "The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types." title: str | None "Display title. The page title for `scraped_link`, the artifact name for `artifact`, and the task title for `task` types. `null` on other types." type: Required[str] - 'The attachment type. One of `"file"`, `"scraped_link"`, `"artifact"`, `"task"`, `"media"`, `"action"`, or `"chart"`. Determines which additional fields are present.' + 'The attachment type. One of `"file"`, `"scraped_link"`, `"artifact"`, `"task"`, `"media"`, `"action"`, `"chart"`, or `"structured_data"`. Determines which additional fields are present.' url: str | None "URL to access the resource. A signed download URL for `file` and `artifact` types; the original URL for `scraped_link`; a media playback URL for `media`. `null` on `task` and `action` types." variants: list[MessageUpdatedPayloadMessageAttachmentsItemVariantsItem] | None @@ -724,7 +728,8 @@ class LocalToolCancelledPayload(TypedDict, total=False): # Channel for real-time chat messaging. # Supports team-scoped and user-scoped threads with keyed, transient, and direct -# thread access patterns. +# thread access patterns, plus org-scoped joins for organization-visibility +# threads, where org membership alone grants read and post. class ApiChatChannel: def __init__(self, channel, join_response=None): self._channel = channel @@ -826,6 +831,38 @@ async def join_team_transient( join_response = await channel.join(payload) return cls(channel, join_response) + # Join an organization-visibility thread by ID + @staticmethod + def topic_org_thread(org_id: str, thread_id: str) -> str: + return f"api:chat:org:{org_id}:thread:{thread_id}" + + # Join an organization-visibility thread by ID + @classmethod + async def join_org_thread( + cls, + socket: "Socket", + org_id: str, + thread_id: str, + *, + after_cursor: str | None = None, + before_cursor: str | None = None, + include_metadata: bool | None = None, + limit: int | None = None, + ) -> "ApiChatChannel": + topic = cls.topic_org_thread(org_id, thread_id) + channel = socket.channel(topic) + payload: dict[str, object] = {} + if after_cursor is not None: + payload["after_cursor"] = after_cursor + if before_cursor is not None: + payload["before_cursor"] = before_cursor + if include_metadata is not None: + payload["include_metadata"] = include_metadata + if limit is not None: + payload["limit"] = limit + join_response = await channel.join(payload) + return cls(channel, join_response) + # Join a user-scoped thread by ID, optionally supplying local tools for a personal thread @staticmethod def topic_user_thread(thread_id: str) -> str: diff --git a/src/archastro/platform/client.py b/src/archastro/platform/client.py index 3455990..a537608 100644 --- a/src/archastro/platform/client.py +++ b/src/archastro/platform/client.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: 6a1a025e96fb +# Content hash: 740a9271cb0f from urllib.parse import urlparse, urlunparse @@ -47,6 +47,7 @@ def __init__( self.agent_skills = self.v1.agent_skills self.agent_tools = self.v1.agent_tools self.agents = self.v1.agents + self.ai = self.v1.ai self.artifacts = self.v1.artifacts self.automation_runs = self.v1.automation_runs self.automations = self.v1.automations @@ -89,7 +90,6 @@ def __init__( self.users = self.v1.users self.work_items = self.v1.work_items self.workflows = self.v1.workflows - self.ai = self.v1.ai self.oauth = self.v1.oauth self._refresh_token: str | None = None self._extra_http_clients: list[HttpClient] = [] @@ -285,6 +285,7 @@ def __init__( self.agent_skills = self.v1.agent_skills self.agent_tools = self.v1.agent_tools self.agents = self.v1.agents + self.ai = self.v1.ai self.artifacts = self.v1.artifacts self.automation_runs = self.v1.automation_runs self.automations = self.v1.automations @@ -327,7 +328,6 @@ def __init__( self.users = self.v1.users self.work_items = self.v1.work_items self.workflows = self.v1.workflows - self.ai = self.v1.ai self.oauth = self.v1.oauth self._refresh_token: str | None = None self._extra_http_clients: list[SyncHttpClient] = [] diff --git a/src/archastro/platform/types/ai.py b/src/archastro/platform/types/ai.py index b538574..f0ae39c 100644 --- a/src/archastro/platform/types/ai.py +++ b/src/archastro/platform/types/ai.py @@ -1,8 +1,8 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: 7e0accb3214e +# Content hash: a2885af89722 -from typing import Any +from typing import Annotated, Any, Literal from pydantic import BaseModel, Field @@ -215,6 +215,85 @@ class AICompletionResult(BaseModel): ) +class AIEvaluationAnswerBoolean(BaseModel): + """ + Probability that the statement is true, in `[0, 1]`. + """ + + id: str + probability: float + type: Literal["boolean"] = "boolean" + + +class AIEvaluationAnswerChoice(BaseModel): + """ + Selected option plus the full probability distribution. + """ + + choice: str + confidence: float | None = None + id: str + probabilities: dict[str, Any] + type: Literal["choice"] = "choice" + + +class AIEvaluationAnswerScore(BaseModel): + """ + Probability-weighted position along the caller-defined levels. + """ + + confidence: float | None = None + id: str + legend: dict[str, Any] + probabilities: dict[str, Any] + score: float + type: Literal["score"] = "score" + + +# One typed evaluation answer. `type` selects boolean, choice, or score. +# `id` matches the question id. +AIEvaluationAnswer = Annotated[ + AIEvaluationAnswerBoolean | AIEvaluationAnswerChoice | AIEvaluationAnswerScore, + Field(discriminator="type"), +] + + +class AIEvaluationUsage(BaseModel): + """ + Token counts for one evaluation request. + """ + + input_tokens: int | None = Field( + default=None, + description="Provider-reported input tokens. `null` when the provider omitted the count.", + ) + output_tokens: int | None = Field( + default=None, + description="Provider-reported output tokens. `null` when the provider omitted the count.", + ) + + +class AIEvaluationResult(BaseModel): + """ + Result of an evaluation request: typed answers, the model that ran, and + token usage. + """ + + answers: list[AIEvaluationAnswer] = Field( + ..., + description="Typed answers. Each value is a boolean, choice, or score object with the question `id`.", + ) + model: str = Field(..., description="Model identifier that produced the answers.") + session_id: str | None = Field( + default=None, + description="UUID grouping this evaluation's usage record. Generated when omitted on the request.", + ) + usage: AIEvaluationUsage | None = Field( + default=None, + description="Token usage for this request. `null` when usage data is unavailable.", + ) + + class AIImageResult(BaseModel): """ The result returned by an AI image generation or editing operation. Contains the generated image (as inline data or a URL) along with dimension, size, and usage metadata. diff --git a/src/archastro/platform/types/common.py b/src/archastro/platform/types/common.py index 4de0207..d89c630 100644 --- a/src/archastro/platform/types/common.py +++ b/src/archastro/platform/types/common.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: de3c1b188a0c +# Content hash: dbf264aff25a from datetime import datetime from typing import Annotated, Any, Literal @@ -417,6 +417,10 @@ class Attachment(BaseModel): default=None, description="Width in pixels of the scraped preview image. Present on `scraped_link` type only. `null` otherwise.", ) + key: str | None = Field( + default=None, + description='For `structured_data` type, what the data is about as set by the sender (for example `"pr:14963"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.', + ) media_type: str | None = Field( default=None, description='The media category, e.g. `"video"` or `"audio"`. Present on `media` type only; omitted otherwise.', @@ -427,7 +431,7 @@ class Attachment(BaseModel): ) object: dict[str, Any] | None = Field( default=None, - description="The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types.", + description="The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types.", ) title: str | None = Field( default=None, @@ -435,7 +439,7 @@ class Attachment(BaseModel): ) type: str = Field( ..., - description='The attachment type. One of `"file"`, `"scraped_link"`, `"artifact"`, `"task"`, `"media"`, `"action"`, or `"chart"`. Determines which additional fields are present.', + description='The attachment type. One of `"file"`, `"scraped_link"`, `"artifact"`, `"task"`, `"media"`, `"action"`, `"chart"`, or `"structured_data"`. Determines which additional fields are present.', ) url: str | None = Field( default=None, diff --git a/src/archastro/platform/types/teams.py b/src/archastro/platform/types/teams.py index 61bfcef..21bc36a 100644 --- a/src/archastro/platform/types/teams.py +++ b/src/archastro/platform/types/teams.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: bd3fc30a03ad +# Content hash: 6ab488d596c8 from datetime import datetime from typing import Any @@ -63,6 +63,20 @@ class Team(BaseModel): ) +class TeamDeleteImpactResponse(BaseModel): + """ + The stored custom-object rows that a Team deletion will physically remove. + """ + + custom_object_count: int = Field( + ..., description="All custom-object rows owned by the Team, including soft-deleted rows." + ) + custom_objects_physically_deleted: bool = Field( + ..., + description="Whether Team deletion physically deletes these rows; no restore is provided.", + ) + + class TeamInvite(BaseModel): """ A team invite containing a short alphanumeric code that other users can present to join the team. diff --git a/src/archastro/platform/types/threads.py b/src/archastro/platform/types/threads.py index 41f1664..d35b14e 100644 --- a/src/archastro/platform/types/threads.py +++ b/src/archastro/platform/types/threads.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: 60f997dab0c6 +# Content hash: fed6220aebf2 from datetime import datetime from typing import Any, Literal @@ -65,7 +65,7 @@ class Thread(BaseModel): ) kind: str | None = Field( default=None, - description='Thread subtype: `"standard"` for ordinary threads, `"personal"` for a user-and-owned-agents roster, `"slack_mirror"` for the membership-strict mirror of a Slack channel, or `"slashwork_mirror"` for the membership-strict mirror of a Slashwork group. `personal` is an explicit user-thread creation option; mirror kinds are server-derived.', + description='Thread subtype: `"standard"` for ordinary threads, `"personal"` for a user-and-owned-agents roster, `"feed"` for a post feed with inline replies, `"slack_mirror"` for the membership-strict mirror of a Slack channel, or `"slashwork_mirror"` for the membership-strict mirror of a Slashwork group. `personal` and `feed` are explicit creation options; mirror kinds are server-derived.', ) last_activity: str | None = Field( default=None, @@ -158,9 +158,9 @@ class Thread(BaseModel): default=None, description="ID of the user who owns this thread (`usr_...`). `null` for team-owned or agent-owned threads.", ) - visibility: Literal["team", "restricted", "private"] = Field( + visibility: Literal["team", "restricted", "private", "org"] = Field( ..., - description="Who can read the thread: `team` for every owning-team member, `restricted` for team-readable threads with an explicit roster, or `private` for roster-only access.", + description="Who can read the thread: `team` for every owning-team member, `restricted` for team-readable threads with an explicit roster, `private` for roster-only access, or `org` for every member of the owning organization.", ) diff --git a/src/archastro/platform/v1/__init__.py b/src/archastro/platform/v1/__init__.py index d224134..f16c19d 100644 --- a/src/archastro/platform/v1/__init__.py +++ b/src/archastro/platform/v1/__init__.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: 54d6fea29e1b +# Content hash: a79a7ec7a9c5 from ..runtime.http_client import HttpClient, SyncHttpClient from .resources.activity_feed import ActivityFeedResource, AsyncActivityFeedResource @@ -100,6 +100,7 @@ def __init__(self, http: SyncHttpClient): self.agent_skills = AgentSkillResource(http) self.agent_tools = AgentToolResource(http) self.agents = AgentResource(http) + self.ai = AiResource(http) self.artifacts = ArtifactResource(http) self.automation_runs = AutomationRunResource(http) self.automations = AutomationResource(http) @@ -142,7 +143,6 @@ def __init__(self, http: SyncHttpClient): self.users = UserResource(http) self.work_items = WorkItemResource(http) self.workflows = WorkflowResource(http) - self.ai = AiResource(http) self.oauth = OauthResource(http) @@ -159,6 +159,7 @@ def __init__(self, http: HttpClient): self.agent_skills = AsyncAgentSkillResource(http) self.agent_tools = AsyncAgentToolResource(http) self.agents = AsyncAgentResource(http) + self.ai = AsyncAiResource(http) self.artifacts = AsyncArtifactResource(http) self.automation_runs = AsyncAutomationRunResource(http) self.automations = AsyncAutomationResource(http) @@ -201,5 +202,4 @@ def __init__(self, http: HttpClient): self.users = AsyncUserResource(http) self.work_items = AsyncWorkItemResource(http) self.workflows = AsyncWorkflowResource(http) - self.ai = AsyncAiResource(http) self.oauth = AsyncOauthResource(http) diff --git a/src/archastro/platform/v1/resources/__init__.py b/src/archastro/platform/v1/resources/__init__.py index 45759a7..f6d5ac9 100644 --- a/src/archastro/platform/v1/resources/__init__.py +++ b/src/archastro/platform/v1/resources/__init__.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: 3a194bfa6a9b +# Content hash: 6852079bf2dc from .activity_feed import ( ActivityFeedResource, # noqa: F401 diff --git a/src/archastro/platform/v1/resources/agents.py b/src/archastro/platform/v1/resources/agents.py index 50f6a94..90a11c5 100644 --- a/src/archastro/platform/v1/resources/agents.py +++ b/src/archastro/platform/v1/resources/agents.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: be99f4bb2c4a +# Content hash: 7de00aaa38e6 from __future__ import annotations @@ -566,8 +566,8 @@ class AgentThreadsInputThread(TypedDict, total=False): "When `true`, the thread is hidden from the default thread list and accessible only by direct link or ID." key: str | None "Client-assigned unique key for idempotent creation or later lookup. Must be unique within the owning organization." - kind: Literal["personal"] | None - "Optional behavioral subtype. `personal` is accepted only for a user-owned thread and limits membership to that user and agents currently owned by them. Mirror kinds remain server-derived and cannot be selected by callers." + kind: Literal["personal", "feed"] | None + "Optional behavioral subtype. `personal` is accepted only for a user-owned thread and limits membership to that user and agents currently owned by them. `feed` is accepted for any owner and renders the thread as a post feed: message lists return top-level posts with their newest replies inline, and agent responses attach to the root post. Mirror kinds remain server-derived and cannot be selected by callers." members: list[AgentThreadsInputThreadMembersItem] | None "Users and agents to add atomically when the thread is created. Each target must pass the same authorization rules as a post-creation member add. Slack mirror threads reject non-empty caller-supplied rosters because their membership is sync-owned." metadata: dict[str, Any] | None @@ -584,8 +584,8 @@ class AgentThreadsInputThread(TypedDict, total=False): "Optional URL-safe identifier. Derived from the title when omitted and unique within the thread owner." title: str | None "Display name for the thread. `null` if omitted, which causes the thread to be untitled." - visibility: Literal["team", "restricted", "private"] | None - "Thread visibility. A team-owned thread with members must explicitly use `restricted` or `private`. User- and agent-owned threads with members default to `private` and reject every other value." + visibility: Literal["team", "restricted", "private", "org"] | None + "Thread visibility. A team-owned thread with members must explicitly use `restricted` or `private`. User- and agent-owned threads with members default to `private` and reject every other value. `org` is only valid on an organization-owned thread with no team, user, or agent owner." class AgentThreadsInput(TypedDict, total=False): diff --git a/src/archastro/platform/v1/resources/ai.py b/src/archastro/platform/v1/resources/ai.py index 69df27d..e307448 100644 --- a/src/archastro/platform/v1/resources/ai.py +++ b/src/archastro/platform/v1/resources/ai.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: 6513b9a30b14 +# Content hash: faea2849d1d8 from __future__ import annotations @@ -19,6 +19,7 @@ AIChatStreamToolCallDelta, AIChatStreamToolResult, AICompletionResult, + AIEvaluationResult, AIImageResult, ) @@ -96,6 +97,8 @@ class StreamCreateInputOpts(TypedDict, total=False): class StreamCreateInput(TypedDict, total=False): "Stream a chat completion" + attribution: dict[str, Any] | None + "Optional caller tags recorded on the LLM-call accounting row. Allowed keys: `task_id` (max 64 chars), `work_id` (max 64), `agent_kind` (one of `worker`, `one_off`, `subagent`, `overseer`, `task_reviewer`, `interactive`, `daemon_job`), `agent_id` (max 64), `client` (max 32). Anything else is a 400." context: dict[str, Any] | None "Key-value map used to resolve template variables in message content. Omit if messages contain no templates." messages: Required[list[StreamCreateInputMessagesItem]] @@ -181,6 +184,8 @@ class CompletionCreateInputOpts(TypedDict, total=False): class CompletionCreateInput(TypedDict, total=False): "Create a chat completion" + attribution: dict[str, Any] | None + "Optional caller tags recorded on the LLM-call accounting row. Allowed keys: `task_id` (max 64 chars), `work_id` (max 64), `agent_kind` (one of `worker`, `one_off`, `subagent`, `overseer`, `task_reviewer`, `interactive`, `daemon_job`), `agent_id` (max 64), `client` (max 32). Anything else is a 400." context: dict[str, Any] | None "Key-value map used to resolve template variables in message content. Omit if messages contain no templates." messages: Required[list[CompletionCreateInputMessagesItem]] @@ -200,6 +205,19 @@ class EmbeddingSimilarityComparisonInput(TypedDict): "Second text to embed and compare." +class EvaluationEvaluationsInput(TypedDict, total=False): + "Create an evaluation" + + model: str | None + "Evaluation model identifier. Omit to use the platform default." + questions: Required[list[dict[str, Any] | dict[str, Any] | dict[str, Any]]] + "Nonempty list of boolean, choice, or score questions. Each question must include `id`, `type`, and `instructions`." + session_id: str | None + "Optional UUID grouping this evaluation under one session in the Developers dashboard. Generated when omitted." + state: Required[Any] + "Shared content the model judges. A string, JSON object, or JSON array. Every question in the request sees this same state." + + class ImageEditsInputImagesItem(TypedDict): image_data: str "The raw image content encoded as a base64 string (standard encoding, no line breaks)." @@ -269,10 +287,19 @@ class ImageGenerationsInput(TypedDict, total=False): "Explicit output width in pixels. Takes precedence over `size` when both are provided. Not supported by all models." +class AiSessionTokenInput(TypedDict, total=False): + "Mint a principal-bound billing session token" + + entitlement: Literal["llm_calls", "run_automation"] | None + restrictions: dict[str, Any] | None + ttl: int | None + user_id: Required[str] + + class ChatModelsResponseDataItem(BaseModel): - capabilities: list[Literal["image", "search", "thinking"]] = Field( + capabilities: list[Literal["image", "search", "temperature", "thinking"]] = Field( ..., - description='Machine-readable model capabilities. `"image"` marks image-input chat, `"search"` marks built-in web search, and `"thinking"` marks models with configurable reasoning. Empty when the catalog entry declares no special capabilities.', + description='Machine-readable model capabilities. `"image"` marks image-input chat, `"search"` marks built-in web search, `"temperature"` marks models that accept the temperature generation parameter, and `"thinking"` marks models with configurable reasoning. Empty when the catalog entry declares no special capabilities.', ) context_window: int | None = Field( default=None, @@ -324,10 +351,52 @@ class EmbeddingSimilarityComparisonResponse(BaseModel): ) +class EvaluationModelsResponseDataItem(BaseModel): + capabilities: list[Literal["image", "search", "temperature", "thinking"]] = Field( + ..., + description='Machine-readable model capabilities. `"image"` marks image-input chat, `"search"` marks built-in web search, `"temperature"` marks models that accept the temperature generation parameter, and `"thinking"` marks models with configurable reasoning. Empty when the catalog entry declares no special capabilities.', + ) + context_window: int | None = Field( + default=None, + description="Maximum context-window size in tokens this model accepts, when the platform publishes it. Use it to size prompt/history against the real window rather than a hardcoded default. `null` for entries whose window the platform does not report (e.g. legacy or mock model listings); clients should apply a conservative fallback in that case.", + ) + default: bool = Field( + ..., + description="`true` for the model the platform selects when an agent has no `default_model` configured, or for the system-wide fallback in image-generation contexts. Exactly one entry in any given model list carries this flag.", + ) + id: str = Field( + ..., + description='Provider-assigned model identifier used when specifying a model on API requests, e.g. `"claude-sonnet-4-6"` or `"gemini-2.5-flash"`.', + ) + input_media_formats: list[str] = Field( + ..., + description='MIME types accepted in chat `content_parts` image/file inputs for this model. For image-capable chat models this includes values such as `"image/png"`. Empty for text-only models.', + ) + name: str = Field( + ..., + description='Human-readable display label for this model, e.g. `"Claude Sonnet 4.6"` or `"Gemini 3.5 Flash (thinking)"`. Render this value directly in pickers rather than attempting to parse or transform `id`. Falls back to the `id` string when the catalog entry does not declare an explicit name.', + ) + output_media_formats: list[str] = Field( + ..., + description="MIME types this model can emit as media in chat responses. Empty for text-output models, including image-understanding models that only return text.", + ) + + +class EvaluationModelsResponse(BaseModel): + """ + Successful response + """ + + data: list[EvaluationModelsResponseDataItem] = Field( + ..., + description="Array of available evaluation model objects. At least one entry is always present.", + ) + + class ImageModelsResponseDataItem(BaseModel): - capabilities: list[Literal["image", "search", "thinking"]] = Field( + capabilities: list[Literal["image", "search", "temperature", "thinking"]] = Field( ..., - description='Machine-readable model capabilities. `"image"` marks image-input chat, `"search"` marks built-in web search, and `"thinking"` marks models with configurable reasoning. Empty when the catalog entry declares no special capabilities.', + description='Machine-readable model capabilities. `"image"` marks image-input chat, `"search"` marks built-in web search, `"temperature"` marks models that accept the temperature generation parameter, and `"thinking"` marks models with configurable reasoning. Empty when the catalog entry declares no special capabilities.', ) context_window: int | None = Field( default=None, @@ -366,6 +435,15 @@ class ImageModelsResponse(BaseModel): ) +class AiSessionTokenResponse(BaseModel): + """ + Successful response + """ + + expires_at: str + token: str + + class StreamCreateEventDone(TypedDict): event: Literal["done"] data: AIChatStreamDone @@ -427,6 +505,7 @@ async def create(self, input: StreamCreateInput) -> AsyncIterator[StreamCreateEv Args: input: Request body. + input.attribution: Optional caller tags recorded on the LLM-call accounting row. Allowed keys: `task_id` (max 64 chars), `work_id` (max 64), `agent_kind` (one of `worker`, `one_off`, `subagent`, `overseer`, `task_reviewer`, `interactive`, `daemon_job`), `agent_id` (max 64), `client` (max 32). Anything else is a 400. input.context: Key-value map used to resolve template variables in message content. Omit if messages contain no templates. input.messages: Ordered list of conversation messages to send to the model. input.opts: Model and sampling configuration for this request. @@ -461,6 +540,7 @@ async def create(self, input: CompletionCreateInput) -> AICompletionResult: Args: input: Request body. + input.attribution: Optional caller tags recorded on the LLM-call accounting row. Allowed keys: `task_id` (max 64 chars), `work_id` (max 64), `agent_kind` (one of `worker`, `one_off`, `subagent`, `overseer`, `task_reviewer`, `interactive`, `daemon_job`), `agent_id` (max 64), `client` (max 32). Anything else is a 400. input.context: Key-value map used to resolve template variables in message content. Omit if messages contain no templates. input.messages: Ordered list of conversation messages to send to the model. input.opts: Model and sampling configuration for this request. @@ -529,6 +609,58 @@ async def similarity_comparison( ) +class AsyncEvaluationResource: + def __init__(self, http: HttpClient): + self._http = http + + async def evaluations(self, input: EvaluationEvaluationsInput) -> AIEvaluationResult: + """ + Create an evaluation + Sends a shared `state` and a list of typed questions to an evaluation + model and returns typed answers. This is not chat completion and not + JSON-schema structured output: there is no generated text. + Each question is a `boolean`, `choice`, or `score` object with its own + `id`. Answers come back as the same three typed objects, each carrying + that `id`. + The authenticated app must have the `llm_calls` entitlement enabled on its + plan. Requests that exceed the plan quota are rejected with `402`. Token + usage is recorded against the authenticated app and organization. + + Args: + input: Request body. + input.model: Evaluation model identifier. Omit to use the platform default. + input.questions: Nonempty list of boolean, choice, or score questions. Each question must include `id`, `type`, and `instructions`. + input.session_id: Optional UUID grouping this evaluation under one session in the Developers dashboard. Generated when omitted. + input.state: Shared content the model judges. A string, JSON object, or JSON array. Every question in the request sees this same state. + + Returns: + Typed answers as a list of boolean, choice, or score objects, plus model and usage. + """ + return await self._http.request( + "/api/v1/ai/evaluation/evaluations", + method="POST", + body=input, + response_type=AIEvaluationResult, + ) + + async def models(self) -> EvaluationModelsResponse: + """ + List available evaluation models + Returns the set of evaluation models that can be used with the evaluations + endpoint. The list reflects models currently enabled for the platform and + includes each model's identifier and whether it is the default. + Use the `id` field from any entry in `data` as the `model` value when + calling the evaluations endpoint. + + Returns: + Successful response + """ + return await self._http.request( + "/api/v1/ai/evaluation/models", + response_type=EvaluationModelsResponse, + ) + + class AsyncImageResource: def __init__(self, http: HttpClient): self._http = http @@ -635,8 +767,26 @@ def __init__(self, http: HttpClient): self._http = http self.chat = AsyncChatResource(http) self.embedding = AsyncEmbeddingResource(http) + self.evaluation = AsyncEvaluationResource(http) self.image = AsyncImageResource(http) + async def session_token(self, input: AiSessionTokenInput) -> AiSessionTokenResponse: + """ + Mint a principal-bound billing session token + + Args: + input: Request body. + + Returns: + Successful response + """ + return await self._http.request( + "/api/v1/ai/session_token", + method="POST", + body=input, + response_type=AiSessionTokenResponse, + ) + class StreamResource: def __init__(self, http: SyncHttpClient): @@ -653,6 +803,7 @@ def create(self, input: StreamCreateInput) -> Iterator[StreamCreateEvent]: Args: input: Request body. + input.attribution: Optional caller tags recorded on the LLM-call accounting row. Allowed keys: `task_id` (max 64 chars), `work_id` (max 64), `agent_kind` (one of `worker`, `one_off`, `subagent`, `overseer`, `task_reviewer`, `interactive`, `daemon_job`), `agent_id` (max 64), `client` (max 32). Anything else is a 400. input.context: Key-value map used to resolve template variables in message content. Omit if messages contain no templates. input.messages: Ordered list of conversation messages to send to the model. input.opts: Model and sampling configuration for this request. @@ -686,6 +837,7 @@ def create(self, input: CompletionCreateInput) -> AICompletionResult: Args: input: Request body. + input.attribution: Optional caller tags recorded on the LLM-call accounting row. Allowed keys: `task_id` (max 64 chars), `work_id` (max 64), `agent_kind` (one of `worker`, `one_off`, `subagent`, `overseer`, `task_reviewer`, `interactive`, `daemon_job`), `agent_id` (max 64), `client` (max 32). Anything else is a 400. input.context: Key-value map used to resolve template variables in message content. Omit if messages contain no templates. input.messages: Ordered list of conversation messages to send to the model. input.opts: Model and sampling configuration for this request. @@ -754,6 +906,58 @@ def similarity_comparison( ) +class EvaluationResource: + def __init__(self, http: SyncHttpClient): + self._http = http + + def evaluations(self, input: EvaluationEvaluationsInput) -> AIEvaluationResult: + """ + Create an evaluation + Sends a shared `state` and a list of typed questions to an evaluation + model and returns typed answers. This is not chat completion and not + JSON-schema structured output: there is no generated text. + Each question is a `boolean`, `choice`, or `score` object with its own + `id`. Answers come back as the same three typed objects, each carrying + that `id`. + The authenticated app must have the `llm_calls` entitlement enabled on its + plan. Requests that exceed the plan quota are rejected with `402`. Token + usage is recorded against the authenticated app and organization. + + Args: + input: Request body. + input.model: Evaluation model identifier. Omit to use the platform default. + input.questions: Nonempty list of boolean, choice, or score questions. Each question must include `id`, `type`, and `instructions`. + input.session_id: Optional UUID grouping this evaluation under one session in the Developers dashboard. Generated when omitted. + input.state: Shared content the model judges. A string, JSON object, or JSON array. Every question in the request sees this same state. + + Returns: + Typed answers as a list of boolean, choice, or score objects, plus model and usage. + """ + return self._http.request( + "/api/v1/ai/evaluation/evaluations", + method="POST", + body=input, + response_type=AIEvaluationResult, + ) + + def models(self) -> EvaluationModelsResponse: + """ + List available evaluation models + Returns the set of evaluation models that can be used with the evaluations + endpoint. The list reflects models currently enabled for the platform and + includes each model's identifier and whether it is the default. + Use the `id` field from any entry in `data` as the `model` value when + calling the evaluations endpoint. + + Returns: + Successful response + """ + return self._http.request( + "/api/v1/ai/evaluation/models", + response_type=EvaluationModelsResponse, + ) + + class ImageResource: def __init__(self, http: SyncHttpClient): self._http = http @@ -857,4 +1061,22 @@ def __init__(self, http: SyncHttpClient): self._http = http self.chat = ChatResource(http) self.embedding = EmbeddingResource(http) + self.evaluation = EvaluationResource(http) self.image = ImageResource(http) + + def session_token(self, input: AiSessionTokenInput) -> AiSessionTokenResponse: + """ + Mint a principal-bound billing session token + + Args: + input: Request body. + + Returns: + Successful response + """ + return self._http.request( + "/api/v1/ai/session_token", + method="POST", + body=input, + response_type=AiSessionTokenResponse, + ) diff --git a/src/archastro/platform/v1/resources/artifacts.py b/src/archastro/platform/v1/resources/artifacts.py index e9c4564..833622a 100644 --- a/src/archastro/platform/v1/resources/artifacts.py +++ b/src/archastro/platform/v1/resources/artifacts.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: 257a07ac71e4 +# Content hash: 5e614d5e0347 from __future__ import annotations @@ -54,7 +54,9 @@ class ArtifactCreateInput(TypedDict, total=False): class ArtifactReplaceInputFile(TypedDict, total=False): data: Required[str] - "Base64-encoded binary content." + "File content encoded according to file.encoding." + encoding: Literal["base64", "utf8"] | None + "Data encoding; defaults to base64. Use utf8 for script-generated text." filename: str | None "Original filename for the uploaded file." mime_type: str | None diff --git a/src/archastro/platform/v1/resources/custom_objects.py b/src/archastro/platform/v1/resources/custom_objects.py index 23407b1..f7c91ec 100644 --- a/src/archastro/platform/v1/resources/custom_objects.py +++ b/src/archastro/platform/v1/resources/custom_objects.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: c863576cd3e0 +# Content hash: 281bca96ed4e from __future__ import annotations @@ -114,6 +114,8 @@ class CustomObjectReplaceInput(TypedDict, total=False): acl: CustomObjectReplaceInputAcl | None "Updated access control list. Supports full replacement via `grants` or targeted `add`/`remove` operations." + expected_version: int | None + "Version number the caller expects to be current. If the object's actual current version does not match, the request returns 409 to signal a concurrent modification. Omit to skip optimistic locking and keep the existing OCC merge retry." field_ops: dict[str, Any] | None "Granular array operations to apply per field (e.g. append, prepend, remove). A field must not appear in both `fields` and `field_ops`." fields: dict[str, Any] | None @@ -435,11 +437,15 @@ async def replace( compatible combination. The same field name must not appear in both `fields` and `field_ops`, which returns 422. Returns 404 if the object does not exist or has been deleted. + Use `expected_version` for optimistic concurrency: if the object's current + `aggregate_version` does not match, the request returns 409 and does not + retry the caller write. Omit it to keep the existing OCC merge retry. Args: object: Custom object ID (`cobj_...`) to update. input: Request body. input.acl: Updated access control list. Supports full replacement via `grants` or targeted `add`/`remove` operations. + input.expected_version: Version number the caller expects to be current. If the object's actual current version does not match, the request returns 409 to signal a concurrent modification. Omit to skip optimistic locking and keep the existing OCC merge retry. input.field_ops: Granular array operations to apply per field (e.g. append, prepend, remove). A field must not appear in both `fields` and `field_ops`. input.fields: Key-value map of field values to merge into the object. Only the supplied keys are affected. input.type: Schema type identifier (`lookup_key`) of the object. Optional; used for routing context only. @@ -642,11 +648,15 @@ def replace(self, object: str, input: CustomObjectReplaceInput) -> CustomObjectR compatible combination. The same field name must not appear in both `fields` and `field_ops`, which returns 422. Returns 404 if the object does not exist or has been deleted. + Use `expected_version` for optimistic concurrency: if the object's current + `aggregate_version` does not match, the request returns 409 and does not + retry the caller write. Omit it to keep the existing OCC merge retry. Args: object: Custom object ID (`cobj_...`) to update. input: Request body. input.acl: Updated access control list. Supports full replacement via `grants` or targeted `add`/`remove` operations. + input.expected_version: Version number the caller expects to be current. If the object's actual current version does not match, the request returns 409 to signal a concurrent modification. Omit to skip optimistic locking and keep the existing OCC merge retry. input.field_ops: Granular array operations to apply per field (e.g. append, prepend, remove). A field must not appear in both `fields` and `field_ops`. input.fields: Key-value map of field values to merge into the object. Only the supplied keys are affected. input.type: Schema type identifier (`lookup_key`) of the object. Optional; used for routing context only. diff --git a/src/archastro/platform/v1/resources/files.py b/src/archastro/platform/v1/resources/files.py index 1696538..cb7a384 100644 --- a/src/archastro/platform/v1/resources/files.py +++ b/src/archastro/platform/v1/resources/files.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: 03df018ed706 +# Content hash: 452760534483 from __future__ import annotations @@ -88,6 +88,13 @@ async def create(self, input: FileCreateInput) -> StorageFile: Creates a new file from base64-encoded content and returns the resulting file object, including a signed download URL. Use this endpoint to store images, documents, or other binary assets that can then be referenced by agents, teams, or users. + The JSON body uses Platform's default 8,000,000-byte parser budget; the + ArchDev Platform proxy has a separate 32 MiB request cap. Base64 requires + `4 * ceil(binary_bytes / 3)` bytes, plus the UTF-8 JSON envelope (including + filename, owner IDs, escaping and other fields). For an envelope of E bytes, + budget at most `3 * floor((8,000,000 - E) / 4)` binary bytes: less than + 6,000,000 bytes (about 5.72 MiB). Do not rely on parser chunk overshoot. + Oversized JSON requests are rejected with HTTP 413 before upload processing. App scope is derived from the authenticated viewer's bearer token or publishable key. You may optionally associate the file with an organization, team, user, or agent by passing the corresponding ID. If no owner is specified and the viewer is a user, the @@ -253,6 +260,13 @@ def create(self, input: FileCreateInput) -> StorageFile: Creates a new file from base64-encoded content and returns the resulting file object, including a signed download URL. Use this endpoint to store images, documents, or other binary assets that can then be referenced by agents, teams, or users. + The JSON body uses Platform's default 8,000,000-byte parser budget; the + ArchDev Platform proxy has a separate 32 MiB request cap. Base64 requires + `4 * ceil(binary_bytes / 3)` bytes, plus the UTF-8 JSON envelope (including + filename, owner IDs, escaping and other fields). For an envelope of E bytes, + budget at most `3 * floor((8,000,000 - E) / 4)` binary bytes: less than + 6,000,000 bytes (about 5.72 MiB). Do not rely on parser chunk overshoot. + Oversized JSON requests are rejected with HTTP 413 before upload processing. App scope is derived from the authenticated viewer's bearer token or publishable key. You may optionally associate the file with an organization, team, user, or agent by passing the corresponding ID. If no owner is specified and the viewer is a user, the diff --git a/src/archastro/platform/v1/resources/orgs.py b/src/archastro/platform/v1/resources/orgs.py index 2054d9c..65e2ceb 100644 --- a/src/archastro/platform/v1/resources/orgs.py +++ b/src/archastro/platform/v1/resources/orgs.py @@ -1,15 +1,1455 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: db5e3465b54b +# Content hash: 76f06a2bde7f from __future__ import annotations +import builtins from datetime import datetime -from typing import Literal +from typing import Any, Literal, Required, TypedDict from pydantic import BaseModel, Field from ...runtime.http_client import HttpClient, SyncHttpClient +from ...types.threads import Thread + + +class OrgThreadCreateInputThreadMembersItem(TypedDict): + id: str + "Public user (`usr_...`) or agent (`agt_...`) ID matching `type`." + type: Literal["user", "agent"] + "Member kind. Use `user` for a user ID or `agent` for an agent ID." + + +class OrgThreadCreateInputThreadProfilePicture(TypedDict, total=False): + data: str | None + "Base64-encoded image bytes." + filename: str | None + "Original filename of the uploaded image, used for display and content-type inference." + mime_type: str | None + 'MIME type of the image, e.g. `"image/png"` or `"image/jpeg"`.' + + +class OrgThreadCreateInputThreadSettings(TypedDict, total=False): + agent_enabled: bool | None + "Whether the AI agent is active for this thread. `true` enables AI responses; `false` disables them. Defaults to `true` when settings have not been explicitly configured. `null` when a client explicitly cleared the setting." + + +class OrgThreadCreateInputThread(TypedDict, total=False): + create_legacy_agent: bool | None + "When `true`, provisions a legacy chat agent alongside the thread. Only needed for integrations that depend on the pre-v2 agent model." + description: str | None + "Optional longer description of the thread's purpose. `null` if not provided." + is_unlisted: bool | None + "When `true`, the thread is hidden from the default thread list and accessible only by direct link or ID." + key: str | None + "Client-assigned unique key for idempotent creation or later lookup. Must be unique within the owning organization." + kind: Literal["personal", "feed"] | None + "Optional behavioral subtype. `personal` is accepted only for a user-owned thread and limits membership to that user and agents currently owned by them. `feed` is accepted for any owner and renders the thread as a post feed: message lists return top-level posts with their newest replies inline, and agent responses attach to the root post. Mirror kinds remain server-derived and cannot be selected by callers." + members: list[OrgThreadCreateInputThreadMembersItem] | None + "Users and agents to add atomically when the thread is created. Each target must pass the same authorization rules as a post-creation member add. Slack mirror threads reject non-empty caller-supplied rosters because their membership is sync-owned." + metadata: dict[str, Any] | None + "Arbitrary key-value pairs stored alongside the thread. Values must be strings or numbers." + muted: bool | None + "When `true`, push and in-app notifications for this thread are suppressed for the creating user." + org_id: str | None + "ID of the organization to create the thread under. Defaults to the authenticated user's primary organization when omitted." + profile_picture: OrgThreadCreateInputThreadProfilePicture | None + "Optional profile image for the thread, provided as a base64-encoded payload." + settings: OrgThreadCreateInputThreadSettings | None + "Configuration overrides for the thread, such as AI model selection and context window settings." + slug: str | None + "Optional URL-safe identifier. Derived from the title when omitted and unique within the thread owner." + title: str | None + "Display name for the thread. `null` if omitted, which causes the thread to be untitled." + visibility: Literal["team", "restricted", "private", "org"] | None + "Thread visibility. A team-owned thread with members must explicitly use `restricted` or `private`. User- and agent-owned threads with members default to `private` and reject every other value. `org` is only valid on an organization-owned thread with no team, user, or agent owner." + + +class OrgThreadCreateInput(TypedDict, total=False): + "Create an organization-visibility thread" + + skip_welcome_message: bool | None + "When `true`, suppresses the automatic welcome message that is otherwise sent into the thread on creation. Defaults to `false`." + thread: Required[OrgThreadCreateInputThread] + "Attributes for the new thread. Visibility is forced to `org`." + + +class OrgThreadListResponseDataItemParentMessageAclAddItem(BaseModel): + actions: list[str] = Field( + ..., + description='Array of action strings the principal is permitted to perform, e.g. `["read", "write"]`. Must contain at least one entry.', + ) + principal: str | None = Field( + default=None, + description='The identifier of the principal. A string ID for `"user"`, `"team"`, `"org"`, and `"agent"` types; one of `"admin"`, `"member"`, or `"viewer"` for `"org_role"`; omit entirely when `principal_type` is `"everyone"`.', + ) + principal_type: str = Field( + ..., + description='The kind of principal receiving the grant. One of `"user"`, `"team"`, `"org"`, `"org_role"`, `"agent"`, or `"everyone"`.', + ) + + +class OrgThreadListResponseDataItemParentMessageAclGrantsItem(BaseModel): + actions: list[str] = Field( + ..., + description='Array of action strings the principal is permitted to perform, e.g. `["read", "write"]`. Must contain at least one entry.', + ) + principal: str | None = Field( + default=None, + description='The identifier of the principal. A string ID for `"user"`, `"team"`, `"org"`, and `"agent"` types; one of `"admin"`, `"member"`, or `"viewer"` for `"org_role"`; omit entirely when `principal_type` is `"everyone"`.', + ) + principal_type: str = Field( + ..., + description='The kind of principal receiving the grant. One of `"user"`, `"team"`, `"org"`, `"org_role"`, `"agent"`, or `"everyone"`.', + ) + + +class OrgThreadListResponseDataItemParentMessageAclRemoveItem(BaseModel): + principal: str | None = Field( + default=None, + description='The identifier of the principal to remove. A string ID for `"user"`, `"team"`, `"org"`, and `"agent"` types; one of `"admin"`, `"member"`, or `"viewer"` for `"org_role"`. Omit when `principal_type` is `"everyone"`.', + ) + principal_type: str = Field( + ..., + description='The kind of principal to remove. One of `"user"`, `"team"`, `"org"`, `"org_role"`, `"agent"`, or `"everyone"`.', + ) + + +class OrgThreadListResponseDataItemParentMessageAcl(BaseModel): + add: list[OrgThreadListResponseDataItemParentMessageAclAddItem] | None = Field( + default=None, + description="Patch mode: grants to add or merge into the existing list. Cannot be combined with `grants`.", + ) + grants: list[OrgThreadListResponseDataItemParentMessageAclGrantsItem] | None = Field( + default=None, + description="Replace mode: the complete new list of grants that replaces all existing entries. Send an empty array (`[]`) to clear all grants. Cannot be combined with `add` or `remove`.", + ) + remove: list[OrgThreadListResponseDataItemParentMessageAclRemoveItem] | None = Field( + default=None, + description="Patch mode: principals whose grants should be removed from the existing list. Cannot be combined with `grants`.", + ) + + +class OrgThreadListResponseDataItemParentMessageActorsItemProfilePicture(BaseModel): + file: str | None = Field( + default=None, + description="ID of the underlying storage file (`fil_...`). `null` when the image is not backed by a platform storage file.", + ) + height: int | None = Field( + default=None, description="Height of the image in pixels. `null` if not known." + ) + media: str | None = Field( + default=None, + description="ID of the associated media record (`med_...`). `null` when the image is not linked to a media entity.", + ) + mime_type: str | None = Field( + default=None, + description='MIME type of the image, e.g. `"image/png"` or `"image/jpeg"`. `null` if not known.', + ) + refresh_url: str | None = Field( + default=None, + description="Endpoint URL you can call to obtain a fresh signed `url` when the current one has expired. `null` if the URL does not require refreshing.", + ) + url: str | None = Field( + default=None, + description="Signed or public URL for downloading the image. May be time-limited; use `refresh_url` to obtain a new URL when this one expires.", + ) + width: int | None = Field( + default=None, description="Width of the image in pixels. `null` if not known." + ) + + +class OrgThreadListResponseDataItemParentMessageActorsItem(BaseModel): + alias: str | None = Field( + default=None, + description="Short handle or alias for the actor, used as an alternate display identifier. `null` if not configured.", + ) + id: str | None = Field( + default=None, + description='Composite actor identifier. Format is `"user-"` for human users or `"agent-"` for agents.', + ) + name: str | None = Field( + default=None, + description="Display name of the actor shown in the UI. `null` if no name is set.", + ) + profile_picture: OrgThreadListResponseDataItemParentMessageActorsItemProfilePicture | None = ( + Field( + default=None, + description="Profile picture for the actor. `null` if the actor has no profile picture.", + ) + ) + + +class OrgThreadListResponseDataItemParentMessageAttachmentsItemImageSource(BaseModel): + file: str | None = Field( + default=None, + description="ID of the underlying storage file (`fil_...`). `null` when the image is not backed by a platform storage file.", + ) + height: int | None = Field( + default=None, description="Height of the image in pixels. `null` if not known." + ) + media: str | None = Field( + default=None, + description="ID of the associated media record (`med_...`). `null` when the image is not linked to a media entity.", + ) + mime_type: str | None = Field( + default=None, + description='MIME type of the image, e.g. `"image/png"` or `"image/jpeg"`. `null` if not known.', + ) + refresh_url: str | None = Field( + default=None, + description="Endpoint URL you can call to obtain a fresh signed `url` when the current one has expired. `null` if the URL does not require refreshing.", + ) + url: str | None = Field( + default=None, + description="Signed or public URL for downloading the image. May be time-limited; use `refresh_url` to obtain a new URL when this one expires.", + ) + width: int | None = Field( + default=None, description="Width of the image in pixels. `null` if not known." + ) + + +class OrgThreadListResponseDataItemParentMessageAttachmentsItemVariantsItemImageSource(BaseModel): + file: str | None = Field( + default=None, + description="ID of the underlying storage file (`fil_...`). `null` when the image is not backed by a platform storage file.", + ) + height: int | None = Field( + default=None, description="Height of the image in pixels. `null` if not known." + ) + media: str | None = Field( + default=None, + description="ID of the associated media record (`med_...`). `null` when the image is not linked to a media entity.", + ) + mime_type: str | None = Field( + default=None, + description='MIME type of the image, e.g. `"image/png"` or `"image/jpeg"`. `null` if not known.', + ) + refresh_url: str | None = Field( + default=None, + description="Endpoint URL you can call to obtain a fresh signed `url` when the current one has expired. `null` if the URL does not require refreshing.", + ) + url: str | None = Field( + default=None, + description="Signed or public URL for downloading the image. May be time-limited; use `refresh_url` to obtain a new URL when this one expires.", + ) + width: int | None = Field( + default=None, description="Width of the image in pixels. `null` if not known." + ) + + +class OrgThreadListResponseDataItemParentMessageAttachmentsItemVariantsItem(BaseModel): + content_type: str | None = Field( + default=None, + description='MIME type of this variant\'s file (e.g., `"image/jpeg"`, `"video/mp4"`). `null` if the file is not loaded.', + ) + created_at: datetime | None = Field( + default=None, description="When this variant was created (ISO 8601)." + ) + file: str | None = Field( + default=None, + description="ID of the underlying storage file that backs this variant (`fil_...`).", + ) + filename: str | None = Field( + default=None, + description="Original filename of the uploaded file for this variant. `null` if the file is not loaded.", + ) + height: int | None = Field( + default=None, description="Height of this variant in pixels. `null` if not recorded." + ) + id: str = Field(..., description="Media variant ID (`mvr_...`).") + image_source: ( + OrgThreadListResponseDataItemParentMessageAttachmentsItemVariantsItemImageSource | None + ) = Field( + default=None, + description="Resolved image delivery metadata for this variant, including dimensions and CDN URL. `null` for non-image content types.", + ) + updated_at: datetime | None = Field( + default=None, description="When this variant was last updated (ISO 8601)." + ) + url: str | None = Field( + default=None, + description="Signed download URL for this variant, resolved at request time. `null` if the file is unavailable.", + ) + variant_key: str | None = Field( + default=None, + description='Identifier for this variant\'s processing tier. Common values include `"original"` (the unmodified upload) and `"thumbnail"` (a resized preview).', + ) + width: int | None = Field( + default=None, description="Width of this variant in pixels. `null` if not recorded." + ) + + +class OrgThreadListResponseDataItemParentMessageAttachmentsItem(BaseModel): + content_type: str | None = Field( + default=None, + description='MIME type of the attached file, e.g. `"image/png"` or `"application/pdf"`. Present on `file`, `artifact`, and `media` types. `null` otherwise.', + ) + description: str | None = Field( + default=None, + description="Short description. The page meta-description for `scraped_link`, the artifact description for `artifact`, and the task description for `task` types. `null` on other types.", + ) + filename: str | None = Field( + default=None, + description='Original filename of the attached file, e.g. `"report.pdf"`. Present on `file`, `artifact`, and `media` types. `null` otherwise.', + ) + height: int | None = Field( + default=None, + description="Height in pixels of the media item. Present on `media` type only. `null` otherwise.", + ) + id: str = Field(..., description="Unique identifier for this attachment within the message.") + image_height: int | None = Field( + default=None, + description="Height in pixels of the scraped preview image. Present on `scraped_link` type only. `null` otherwise.", + ) + image_source: OrgThreadListResponseDataItemParentMessageAttachmentsItemImageSource | None = ( + Field( + default=None, + description="Image source metadata for inline rendering. Present on `file`, `scraped_link`, `artifact`, and `media` types when the content is an image. `null` otherwise.", + ) + ) + image_url: str | None = Field( + default=None, + description="URL of the preview image extracted from the scraped page. Present on `scraped_link` type only. `null` otherwise.", + ) + image_width: int | None = Field( + default=None, + description="Width in pixels of the scraped preview image. Present on `scraped_link` type only. `null` otherwise.", + ) + key: str | None = Field( + default=None, + description='For `structured_data` type, what the data is about as set by the sender (for example `"pr:14963"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.', + ) + media_type: str | None = Field( + default=None, + description='The media category, e.g. `"video"` or `"audio"`. Present on `media` type only; omitted otherwise.', + ) + name: str | None = Field( + default=None, + description="Display name of the media item. Present on `media` type only. `null` otherwise.", + ) + object: dict[str, Any] | None = Field( + default=None, + description="The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types.", + ) + title: str | None = Field( + default=None, + description="Display title. The page title for `scraped_link`, the artifact name for `artifact`, and the task title for `task` types. `null` on other types.", + ) + type: str = Field( + ..., + description='The attachment type. One of `"file"`, `"scraped_link"`, `"artifact"`, `"task"`, `"media"`, `"action"`, `"chart"`, or `"structured_data"`. Determines which additional fields are present.', + ) + url: str | None = Field( + default=None, + description="URL to access the resource. A signed download URL for `file` and `artifact` types; the original URL for `scraped_link`; a media playback URL for `media`. `null` on `task` and `action` types.", + ) + variants: list[OrgThreadListResponseDataItemParentMessageAttachmentsItemVariantsItem] | None = ( + Field( + default=None, + description="Array of available encoding variants for the media item (e.g. different resolutions). Present on `media` type only; omitted otherwise.", + ) + ) + version: int | None = Field( + default=None, + description="Version number of the attached artifact at the time of attachment. Present on `artifact` type only. `null` otherwise.", + ) + width: int | None = Field( + default=None, + description="Width in pixels of the media item. Present on `media` type only. `null` otherwise.", + ) + + +class OrgThreadListResponseDataItemParentMessageContextItem(BaseModel): + attributes: dict[str, Any] | None = Field( + default=None, + description="Scalar key-value fields describing the context, such as route, repository, or pull-request number.", + ) + content: str | None = Field( + default=None, + description="Optional context body. The model receives it as escaped XML data, not a system instruction.", + ) + title: str | None = Field( + default=None, description="Optional human-readable label for this context block." + ) + type: str = Field( + ..., + description="Stable context kind. Must start with a lowercase letter and contain only lowercase letters, numbers, dots, dashes, or underscores.", + ) + + +class OrgThreadListResponseDataItemParentMessageReactionsItem(BaseModel): + payload: dict[str, Any] | None = Field( + default=None, + description='Type-specific reaction data. For `"emoji_reaction"` reactions, contains an `emoji` key with the Unicode emoji string (e.g., `" "`).', + ) + type: str = Field( + ..., + description='Reaction type identifier. Currently always `"emoji_reaction"` for emoji-based reactions.', + ) + user: str | None = Field( + default=None, description="Public ID of the user who added the reaction (`usr_...`)." + ) + + +class OrgThreadListResponseDataItemParentMessage(BaseModel): + acl: OrgThreadListResponseDataItemParentMessageAcl | None = Field( + default=None, + description="Access control list for private messages (grants with `read` action). Only returned to resource owners (and privileged/org-admin viewers) via server-side `field_redactions: [acl: :owner]`; `null` for everyone else.", + ) + actors: list[OrgThreadListResponseDataItemParentMessageActorsItem] | None = Field( + default=None, + description="Resolved actor descriptors for the message sender, combining identity and display metadata. Always contains exactly one entry.", + ) + agent: str | None = Field( + default=None, + description="ID of the agent user that sent this message (`agi_...`). `null` for messages sent by human users.", + ) + agent_mode: Literal["cli", "embedded"] | None = Field( + default=None, + description="Local agent execution mode for this message. One of `cli`, `embedded`, or `null` when the message was not created by a local agent execution path.", + ) + attachments: list[OrgThreadListResponseDataItemParentMessageAttachmentsItem] | None = Field( + default=None, + description="Files, links, tasks, media, artifacts, and actions attached to this message. Empty array if there are no attachments.", + ) + branched_thread: str | None = Field( + default=None, + description="ID of the thread that was branched from this message (`thr_...`). `null` if this message has not spawned a branch thread.", + ) + content: str | None = Field( + default=None, + description="Text content of the message. `null` for messages that contain only attachments.", + ) + context: list[OrgThreadListResponseDataItemParentMessageContextItem] | None = Field( + default=None, + description="Immutable structured context captured when the message was posted. Each entry has `type`, optional `title` and `content`, and scalar `attributes`. Always present; defaults to an empty array. Context is delivered to agents as escaped XML data, not as system instructions.", + ) + created_at: str | None = Field( + default=None, description="When the message was posted (ISO 8601)." + ) + has_replies: bool | None = Field( + default=None, + description="Whether this message has at least one reply. Only present when explicitly requested or computed by the server.", + ) + id: str = Field(..., description="Message ID (`msg_...`).") + idempotency_key: str | None = Field( + default=None, + description="Client-supplied idempotency key used to deduplicate message sends. `null` if the sender did not provide one.", + ) + is_deleted: bool | None = Field( + default=None, + description="Whether this message is a deletion tombstone. `true` only on the `message_updated` broadcast emitted when a message is deleted: the original content is replaced with a placeholder and the message no longer exists on the server. Always `false` for live messages.", + ) + legacy_agent: str | None = Field( + default=None, + description="Identifier of the legacy chat agent that sent this message, if applicable. `null` for messages sent by users or modern agent users.", + ) + metadata: dict[str, Any] | None = Field( + default=None, + description="Arbitrary key-value metadata attached to the message. Always present; defaults to an empty object when no metadata has been set.", + ) + org: str | None = Field( + default=None, description="ID of the organization that owns this message (`org_...`)." + ) + reactions: list[OrgThreadListResponseDataItemParentMessageReactionsItem] | None = Field( + default=None, + description="Emoji and other reactions added to this message by users. Empty array if no reactions have been added or the association is not preloaded.", + ) + rendering_mode: str | None = Field( + default=None, + description='Display hint for how the message should be rendered. One of `"reply"`, `"direct"`, or `"inline"`. `null` for user-authored messages, which are always rendered as standard replies.', + ) + replies: list[dict[str, Any]] | None = Field( + default=None, + description="Inline array of reply messages, each serialized as a full message object. Only present when the server has preloaded replies for this message.", + ) + replies_after_cursor: str | None = Field( + default=None, + description="Opaque pagination cursor to fetch replies posted after the current page. Only present when inline replies are included in the response.", + ) + replies_before_cursor: str | None = Field( + default=None, + description="Opaque pagination cursor to fetch replies posted before the current page. Only present when inline replies are included in the response.", + ) + reply_count: int | None = Field( + default=None, + description="Total number of direct replies to this message. Only present when explicitly requested or computed by the server.", + ) + reply_to: dict[str, Any] | None = Field( + default=None, + description="The parent message this message is a reply to, expanded as a full message object when loaded. `null` if this is a top-level message or the association is not preloaded.", + ) + root_message_id: str | None = Field( + default=None, + description="ID of the root message in this reply chain (`msg_...`). `null` for a top-level message. The value is persisted when the reply is created, so callers can correlate a multi-turn session without walking parent messages.", + ) + sandbox: str | None = Field( + default=None, + description="ID of the developer sandbox this message belongs to (`dsb_...`). `null` for non-sandbox messages.", + ) + team: str | None = Field( + default=None, + description="ID of the team this message is scoped to (`tem_...`). `null` if the message is not team-scoped.", + ) + thread: str | None = Field( + default=None, description="ID of the thread this message belongs to (`thr_...`)." + ) + type: str | None = Field( + default=None, + description="Optional client-defined classification for the message (for example `note` or `status`). Free-form string up to 64 characters. The value `system` is reserved for platform-authored messages and cannot be set by clients. `null` when unset.", + ) + user: str | dict[str, Any] | None = Field( + default=None, + description="The human user who sent this message. Returns a public ID string (`usr_...`) when the association is not preloaded, or an expanded user object when it is. `null` for messages sent by agents.", + ) + visibility: Literal["default", "private"] | None = Field( + default=None, + description="Message-level visibility. `default` is visible to anyone who can see the parent thread. `private` is restricted to the sender and explicit ACL `read` grantees.", + ) + + +class OrgThreadListResponseDataItemParticipantsItem(BaseModel): + alias: str | None = Field( + default=None, description="Short handle or alias for the user. `null` if not set." + ) + app: str | None = Field( + default=None, + description="ID of the app this user (and their access token) is scoped to (`dap_...`). `null` if the user is not scoped to an app.", + ) + app_name: str | None = Field( + default=None, + description="Display name of the user's app. `null` when the app association was not preloaded by the caller.", + ) + created_by_agent_user: str | None = Field( + default=None, + description="Agent user that created this account (`usr_...`). `null` unless an agent created it.", + ) + created_by_developer: str | None = Field( + default=None, + description="Developer account that created this user (`dva_...`). `null` unless created via a developer token.", + ) + created_by_org: str | None = Field( + default=None, + description="Org of the principal that created this user (`org_...`). `null` on legacy rows.", + ) + created_by_team: str | None = Field( + default=None, + description="Team that created this user (`tem_...`). `null` unless created as a team.", + ) + created_by_user: str | None = Field( + default=None, + description="User who created this account (`usr_...`). `null` on self-signup or legacy rows.", + ) + email: str | None = Field(default=None, description="Email address of the user.") + id: str = Field(..., description="User ID (`usr_...`).") + is_system_user: bool | None = Field( + default=None, + description="`true` if this account is an internal system user rather than a human. System users are created automatically by the platform.", + ) + metadata: dict[str, Any] | None = Field( + default=None, + description="Arbitrary key-value metadata attached to the user. Defaults to an empty object.", + ) + name: str | None = Field( + default=None, + description="Full display name of the user. `null` if the user has not set a name.", + ) + org: str | None = Field( + default=None, + description="ID of the organization this user belongs to (`org_...`). `null` if the user is not a member of any organization.", + ) + org_name: str | None = Field( + default=None, + description="Display name of the user's organization. `null` when the user is not in an org, or when the org association was not preloaded by the caller.", + ) + org_role: str | None = Field( + default=None, + description='Role of the user within their organization. One of `"admin"`, `"member"`, or `"viewer"`. `null` when the user is not a member of any organization.', + ) + org_slug: str | None = Field( + default=None, + description="Stable workspace slug for the user's organization. `null` when the user is not in an org, or when the org association was not preloaded by the caller.", + ) + sandbox: str | None = Field( + default=None, + description="ID of the sandbox environment this user is scoped to (`sbx_...`). `null` for production users.", + ) + sandbox_name: str | None = Field( + default=None, + description="Display name of the user's sandbox environment. `null` for production users, or when the sandbox association was not preloaded by the caller.", + ) + + +class OrgThreadListResponseDataItemParticipatingAgentsItemAclAddItem(BaseModel): + actions: list[str] = Field( + ..., + description='Array of action strings the principal is permitted to perform, e.g. `["read", "write"]`. Must contain at least one entry.', + ) + principal: str | None = Field( + default=None, + description='The identifier of the principal. A string ID for `"user"`, `"team"`, `"org"`, and `"agent"` types; one of `"admin"`, `"member"`, or `"viewer"` for `"org_role"`; omit entirely when `principal_type` is `"everyone"`.', + ) + principal_type: str = Field( + ..., + description='The kind of principal receiving the grant. One of `"user"`, `"team"`, `"org"`, `"org_role"`, `"agent"`, or `"everyone"`.', + ) + + +class OrgThreadListResponseDataItemParticipatingAgentsItemAclGrantsItem(BaseModel): + actions: list[str] = Field( + ..., + description='Array of action strings the principal is permitted to perform, e.g. `["read", "write"]`. Must contain at least one entry.', + ) + principal: str | None = Field( + default=None, + description='The identifier of the principal. A string ID for `"user"`, `"team"`, `"org"`, and `"agent"` types; one of `"admin"`, `"member"`, or `"viewer"` for `"org_role"`; omit entirely when `principal_type` is `"everyone"`.', + ) + principal_type: str = Field( + ..., + description='The kind of principal receiving the grant. One of `"user"`, `"team"`, `"org"`, `"org_role"`, `"agent"`, or `"everyone"`.', + ) + + +class OrgThreadListResponseDataItemParticipatingAgentsItemAclRemoveItem(BaseModel): + principal: str | None = Field( + default=None, + description='The identifier of the principal to remove. A string ID for `"user"`, `"team"`, `"org"`, and `"agent"` types; one of `"admin"`, `"member"`, or `"viewer"` for `"org_role"`. Omit when `principal_type` is `"everyone"`.', + ) + principal_type: str = Field( + ..., + description='The kind of principal to remove. One of `"user"`, `"team"`, `"org"`, `"org_role"`, `"agent"`, or `"everyone"`.', + ) + + +class OrgThreadListResponseDataItemParticipatingAgentsItemAcl(BaseModel): + add: list[OrgThreadListResponseDataItemParticipatingAgentsItemAclAddItem] | None = Field( + default=None, + description="Patch mode: grants to add or merge into the existing list. Cannot be combined with `grants`.", + ) + grants: list[OrgThreadListResponseDataItemParticipatingAgentsItemAclGrantsItem] | None = Field( + default=None, + description="Replace mode: the complete new list of grants that replaces all existing entries. Send an empty array (`[]`) to clear all grants. Cannot be combined with `add` or `remove`.", + ) + remove: list[OrgThreadListResponseDataItemParticipatingAgentsItemAclRemoveItem] | None = Field( + default=None, + description="Patch mode: principals whose grants should be removed from the existing list. Cannot be combined with `grants`.", + ) + + +class OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionCurrentSolutionOrgLogo( + BaseModel +): + file: str | None = Field( + default=None, + description="ID of the underlying storage file (`fil_...`). `null` when the image is not backed by a platform storage file.", + ) + height: int | None = Field( + default=None, description="Height of the image in pixels. `null` if not known." + ) + media: str | None = Field( + default=None, + description="ID of the associated media record (`med_...`). `null` when the image is not linked to a media entity.", + ) + mime_type: str | None = Field( + default=None, + description='MIME type of the image, e.g. `"image/png"` or `"image/jpeg"`. `null` if not known.', + ) + refresh_url: str | None = Field( + default=None, + description="Endpoint URL you can call to obtain a fresh signed `url` when the current one has expired. `null` if the URL does not require refreshing.", + ) + url: str | None = Field( + default=None, + description="Signed or public URL for downloading the image. May be time-limited; use `refresh_url` to obtain a new URL when this one expires.", + ) + width: int | None = Field( + default=None, description="Width of the image in pixels. `null` if not known." + ) + + +class OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionCurrentSolutionTemplatesItemDetailsInvokeContractParticipantsItem( + BaseModel +): + description: str | None = Field( + default=None, + description="Workflow-authored explanation of the slot's role. `null` when the workflow declares none.", + ) + name: str = Field( + ..., + description="The slot's name, as referenced by the workflow. Supply the chosen agent under the top-level `participants[name]` field when invoking.", + ) + required: bool = Field( + ..., + description="Whether the workflow requires this slot to be filled for the run to complete its embedded stages.", + ) + type: str = Field( + ..., + description='The kind of principal the slot accepts. Currently always `"agent_user"` the value supplied at invoke is an agent ID (`agi_...`).', + ) + + +class OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionCurrentSolutionTemplatesItemDetailsInvokeContractPrefills( + BaseModel +): + participants: dict[str, Any] | None = Field( + default=None, + description="Participant slot-to-agent mappings applied by the platform. Caller values at these slots must match exactly.", + ) + payload: dict[str, Any] | None = Field( + default=None, + description="Partial invocation payload applied by the platform. A caller may omit these values, but supplying a different value at any locked path is rejected.", + ) + + +class OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionCurrentSolutionTemplatesItemDetailsInvokeContract( + BaseModel +): + input_schema: dict[str, Any] | None = Field( + default=None, + description="JSON Schema validated against the whole invoke payload, from the automation's `input_schema_config`. `null` when none is configured.", + ) + participants: ( + list[ + OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionCurrentSolutionTemplatesItemDetailsInvokeContractParticipantsItem + ] + | None + ) = Field( + default=None, + description="Named participant slots declared by the workflow, sorted by name. `null` when the workflow declares none. Values supplied under the top-level `participants` field are agent IDs.", + ) + prefills: OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionCurrentSolutionTemplatesItemDetailsInvokeContractPrefills = Field( + ..., + description="Owner-controlled payload and participant values the platform applies to every invocation. Supplying a conflicting value is rejected.", + ) + + +class OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionCurrentSolutionTemplatesItemDetails( + BaseModel +): + automation_type: str | None = Field( + default=None, + description="Automation execution type (`invoked`, `scheduled`, or `trigger`). `null` when the template body does not declare one.", + ) + invoke_contract: ( + OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionCurrentSolutionTemplatesItemDetailsInvokeContract + | None + ) = Field( + default=None, + description="Schema-driven payload and participant inputs for an invoked automation. Used by installation clients to collect locked prefills before provisioning. `null` for non-invoked automation types.", + ) + type: Literal["automation"] = Field( + default="automation", + description="Template-details discriminator. Always `automation` for this variant.", + ) + + +class OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionCurrentSolutionTemplatesItem( + BaseModel +): + description: str | None = Field( + default=None, + description="Short prose blurb from the template body's `description:` field. `null` when the body doesn't set one. Used as the card subhead in the Library carousel.", + ) + details: ( + OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionCurrentSolutionTemplatesItemDetails + | None + ) = Field( + default=None, + description="Template-kind-specific details selected by the `type` discriminator. `null` when this template kind has no additional details.", + ) + display_name: str | None = Field( + default=None, + description="Human-facing label from the template body's `display_name:` field. `null` when the body doesn't set one. Library carousels use this for the card title, falling back to a humanized `name`.", + ) + id: str | None = Field( + default=None, + description="Template config ID (`cfg_...`). `null` for inline-only templates.", + ) + kind: str = Field( + ..., + description="Template config kind, or `SolutionTemplateRef` / `SolutionTemplatePath` when unresolved.", + ) + lookup_key: str | None = Field( + default=None, + description="Lookup key stamped on the template config at import time. `null` when no lookup key was assigned.", + ) + name: str | None = Field( + default=None, + description="Canonical name from the template body. For `AgentTemplate` this doubles as the human-facing label; for `AgentToolTemplate` it's the LLM-facing tool function identifier (snake_case); for `AgentRoutineTemplate` it's the routine identifier (kebab-case). Clients rendering carousels should prefer `display_name` and fall back to humanizing `name`.", + ) + readme_url: str | None = Field( + default=None, + description="Relative path to the public README endpoint with a signed token already embedded, scoped to this template's bundled markdown asset. `null` when the Solution body's `templates[].readme_path` is unset for this entry. Token expires in 1 hour refresh via `GET /api/v1/solutions/:solution`.", + ) + virtual_path: str | None = Field( + default=None, + description="Stable virtual path assigned to the template config. `null` when no virtual path was set.", + ) + + +class OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionCurrentSolution(BaseModel): + category_keys: list[str] | None = Field( + default=None, + description="Category tag keys declared in the Solution body, used to group Solutions in the catalog. An empty array when the body declares none.", + ) + created_at: str | None = Field( + default=None, description="When the Solution config was first imported (ISO 8601)." + ) + description: str | None = Field( + default=None, + description="Short tagline or summary declared in the Solution body, used as the card subhead in catalog UIs. `null` when the Solution body does not set one.", + ) + events: dict[str, Any] | None = Field( + default=None, + description="Custom analytics events declared in the Solution body's `events:` manifest a map of event key (snake_case) to its definition (`label`, optional `description`, optional typed `fields`). Dashboards use the `label` as the event's display name. Present as an empty object when the body declares none.", + ) + id: str = Field(..., description="Solution config ID (`cfg_...`).") + image_url: str | None = Field( + default=None, + description="Absolute URL of the Solution's cover image the bundled asset the body's `image:` field names. A stable, non-expiring capability URL (like `org_logo.url`), safe to hold in caches and OpenGraph tags; it 404s if the Solution stops declaring a cover. `null` when the Solution has no cover image. Org-only rows remain `null`; when a list entry merges an org copy with its system counterpart, it may reuse the system row's public cover URL. Permanent URLs are never minted for private org assets.", + ) + installed_config_ids: list[str] = Field( + ..., + description="Config IDs (`cfg_...`) of this Solution's installations in the viewer's organization. The array is empty when the Solution is visible only from the system catalog.", + ) + kind: str = Field(..., description='Resource type. Always `"Solution"`.') + latest_solution: str | None = Field( + default=None, + description="When `upgrade_available` is `true`, the system-scope Solution config ID (`cfg_...`) that should be used as the upgrade source. `null` otherwise.", + ) + latest_version: str | None = Field( + default=None, + description="When `upgrade_available` is `true`, the higher system-scope `solution_version` available to upgrade to. `null` otherwise.", + ) + lookup_key: str | None = Field( + default=None, + description="The lookup key stored on the Solution config, if one was assigned during import. `null` when no lookup key was set.", + ) + metadata: dict[str, Any] | None = Field( + default=None, + description="Arbitrary key-value metadata declared in the Solution body (e.g. category or display hints). Present as an empty object when the body declares none.", + ) + name: str | None = Field( + default=None, + description="Human-facing display name declared in the Solution body. `null` when the Solution body does not set one.", + ) + org: str | None = Field( + default=None, + description="Organization ID (`org_...`) that owns this Solution config, when the Solution is scoped to a specific org. `null` for system-scope (app-level) Solutions.", + ) + org_logo: ( + OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionCurrentSolutionOrgLogo + | None + ) = Field( + default=None, + description="Canonical image-source object for the resolved `org`'s logo, used as the principal category section glyph. The `url` is a stable, non-expiring capability URL (`refresh_url` is `null` there is nothing to refresh). `null` when `org_slug` is `null` or the org has no logo.", + ) + org_name: str | None = Field( + default=None, + description="Display name of the resolved `org`. Pairs with `org_slug` as the principal catalog category's label. `null` when `org_slug` is `null`.", + ) + org_slug: str | None = Field( + default=None, + description="Resolved slug of the Solution body's `org` (the publishing organization), when set and it resolves to a real org visible to the viewer. When present this is the Solution's principal catalog category key clients group the Solution under this org ahead of `category_keys`. `null` when the body has no `org` or it doesn't resolve.", + ) + owners: list[str] = Field( + ..., + description='Owner scopes this Solution appears under. Members: `"system"` (app-level system scope) and/or `"org"` (viewer\'s org scope).', + ) + readme_url: str | None = Field( + default=None, + description="Relative path to the public README endpoint with a signed token already embedded. `null` when the Solution has no README. Token expires in 1 hour refresh via `GET /api/v1/solutions/:solution`.", + ) + screenshot_urls: list[str] | None = Field( + default=None, + description="Absolute URLs of the Solution's gallery screenshots the bundled assets the body's `screenshots:` field names, in declared order. Each is a stable, non-expiring capability URL with the same cacheability contract as `image_url` (one shared token, a `v` cache key, and a `file` param selecting the screenshot); a URL 404s if the Solution stops declaring its screenshot. An empty array when the Solution declares none, and always empty for org-scoped rows the permanent URLs are minted for system-scope (catalog) Solutions only.", + ) + solution_id: str | None = Field( + default=None, + description="Stable UUID declared in the Solution body, used to identify the same logical Solution across multiple installed copies and owner scopes. `null` when the body omits it.", + ) + solution_version: str | None = Field( + default=None, + description='Semver string declared in the Solution body (e.g. `"1.2.0"`). `null` when the body does not declare a version.', + ) + tag_keys: list[str] | None = Field( + default=None, + description="Freeform tag keys declared in the Solution body. An empty array when the body declares none.", + ) + template_kind: str | None = Field( + default=None, + description='Wrapped template kind `"AgentTemplate"`, `"AutomationTemplate"`, `"AgentRoutineTemplate"`, `"AgentToolTemplate"`, `"AgentComputerTemplate"`, or `"SolutionTemplateRef"` for ref-mode bundles.', + ) + templates: list[ + OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionCurrentSolutionTemplatesItem + ] = Field( + ..., + description="Template configs bundled by this Solution, in declaration order the first entry is the deployable template the Solution wraps; the rest are sibling templates the wrapped template references.", + ) + updated_at: str | None = Field( + default=None, description="When the Solution config was last modified (ISO 8601)." + ) + upgrade_available: bool = Field( + ..., + description="`true` when this Solution is installed at the viewer's org scope and the app-level system scope carries a higher `solution_version`. Always `false` for system-only rows.", + ) + virtual_path: str | None = Field( + default=None, + description="The stable virtual path assigned to this Solution config, used as the deduplication key when the same Solution appears under multiple owner scopes. `null` when unset.", + ) + + +class OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionSolutionOrgLogo(BaseModel): + file: str | None = Field( + default=None, + description="ID of the underlying storage file (`fil_...`). `null` when the image is not backed by a platform storage file.", + ) + height: int | None = Field( + default=None, description="Height of the image in pixels. `null` if not known." + ) + media: str | None = Field( + default=None, + description="ID of the associated media record (`med_...`). `null` when the image is not linked to a media entity.", + ) + mime_type: str | None = Field( + default=None, + description='MIME type of the image, e.g. `"image/png"` or `"image/jpeg"`. `null` if not known.', + ) + refresh_url: str | None = Field( + default=None, + description="Endpoint URL you can call to obtain a fresh signed `url` when the current one has expired. `null` if the URL does not require refreshing.", + ) + url: str | None = Field( + default=None, + description="Signed or public URL for downloading the image. May be time-limited; use `refresh_url` to obtain a new URL when this one expires.", + ) + width: int | None = Field( + default=None, description="Width of the image in pixels. `null` if not known." + ) + + +class OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionSolutionTemplatesItemDetailsInvokeContractParticipantsItem( + BaseModel +): + description: str | None = Field( + default=None, + description="Workflow-authored explanation of the slot's role. `null` when the workflow declares none.", + ) + name: str = Field( + ..., + description="The slot's name, as referenced by the workflow. Supply the chosen agent under the top-level `participants[name]` field when invoking.", + ) + required: bool = Field( + ..., + description="Whether the workflow requires this slot to be filled for the run to complete its embedded stages.", + ) + type: str = Field( + ..., + description='The kind of principal the slot accepts. Currently always `"agent_user"` the value supplied at invoke is an agent ID (`agi_...`).', + ) + + +class OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionSolutionTemplatesItemDetailsInvokeContractPrefills( + BaseModel +): + participants: dict[str, Any] | None = Field( + default=None, + description="Participant slot-to-agent mappings applied by the platform. Caller values at these slots must match exactly.", + ) + payload: dict[str, Any] | None = Field( + default=None, + description="Partial invocation payload applied by the platform. A caller may omit these values, but supplying a different value at any locked path is rejected.", + ) + + +class OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionSolutionTemplatesItemDetailsInvokeContract( + BaseModel +): + input_schema: dict[str, Any] | None = Field( + default=None, + description="JSON Schema validated against the whole invoke payload, from the automation's `input_schema_config`. `null` when none is configured.", + ) + participants: ( + list[ + OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionSolutionTemplatesItemDetailsInvokeContractParticipantsItem + ] + | None + ) = Field( + default=None, + description="Named participant slots declared by the workflow, sorted by name. `null` when the workflow declares none. Values supplied under the top-level `participants` field are agent IDs.", + ) + prefills: OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionSolutionTemplatesItemDetailsInvokeContractPrefills = Field( + ..., + description="Owner-controlled payload and participant values the platform applies to every invocation. Supplying a conflicting value is rejected.", + ) + + +class OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionSolutionTemplatesItemDetails( + BaseModel +): + automation_type: str | None = Field( + default=None, + description="Automation execution type (`invoked`, `scheduled`, or `trigger`). `null` when the template body does not declare one.", + ) + invoke_contract: ( + OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionSolutionTemplatesItemDetailsInvokeContract + | None + ) = Field( + default=None, + description="Schema-driven payload and participant inputs for an invoked automation. Used by installation clients to collect locked prefills before provisioning. `null` for non-invoked automation types.", + ) + type: Literal["automation"] = Field( + default="automation", + description="Template-details discriminator. Always `automation` for this variant.", + ) + + +class OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionSolutionTemplatesItem( + BaseModel +): + description: str | None = Field( + default=None, + description="Short prose blurb from the template body's `description:` field. `null` when the body doesn't set one. Used as the card subhead in the Library carousel.", + ) + details: ( + OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionSolutionTemplatesItemDetails + | None + ) = Field( + default=None, + description="Template-kind-specific details selected by the `type` discriminator. `null` when this template kind has no additional details.", + ) + display_name: str | None = Field( + default=None, + description="Human-facing label from the template body's `display_name:` field. `null` when the body doesn't set one. Library carousels use this for the card title, falling back to a humanized `name`.", + ) + id: str | None = Field( + default=None, + description="Template config ID (`cfg_...`). `null` for inline-only templates.", + ) + kind: str = Field( + ..., + description="Template config kind, or `SolutionTemplateRef` / `SolutionTemplatePath` when unresolved.", + ) + lookup_key: str | None = Field( + default=None, + description="Lookup key stamped on the template config at import time. `null` when no lookup key was assigned.", + ) + name: str | None = Field( + default=None, + description="Canonical name from the template body. For `AgentTemplate` this doubles as the human-facing label; for `AgentToolTemplate` it's the LLM-facing tool function identifier (snake_case); for `AgentRoutineTemplate` it's the routine identifier (kebab-case). Clients rendering carousels should prefer `display_name` and fall back to humanizing `name`.", + ) + readme_url: str | None = Field( + default=None, + description="Relative path to the public README endpoint with a signed token already embedded, scoped to this template's bundled markdown asset. `null` when the Solution body's `templates[].readme_path` is unset for this entry. Token expires in 1 hour refresh via `GET /api/v1/solutions/:solution`.", + ) + virtual_path: str | None = Field( + default=None, + description="Stable virtual path assigned to the template config. `null` when no virtual path was set.", + ) + + +class OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionSolution(BaseModel): + category_keys: list[str] | None = Field( + default=None, + description="Category tag keys declared in the Solution body, used to group Solutions in the catalog. An empty array when the body declares none.", + ) + created_at: str | None = Field( + default=None, description="When the Solution config was first imported (ISO 8601)." + ) + description: str | None = Field( + default=None, + description="Short tagline or summary declared in the Solution body, used as the card subhead in catalog UIs. `null` when the Solution body does not set one.", + ) + events: dict[str, Any] | None = Field( + default=None, + description="Custom analytics events declared in the Solution body's `events:` manifest a map of event key (snake_case) to its definition (`label`, optional `description`, optional typed `fields`). Dashboards use the `label` as the event's display name. Present as an empty object when the body declares none.", + ) + id: str = Field(..., description="Solution config ID (`cfg_...`).") + image_url: str | None = Field( + default=None, + description="Absolute URL of the Solution's cover image the bundled asset the body's `image:` field names. A stable, non-expiring capability URL (like `org_logo.url`), safe to hold in caches and OpenGraph tags; it 404s if the Solution stops declaring a cover. `null` when the Solution has no cover image. Org-only rows remain `null`; when a list entry merges an org copy with its system counterpart, it may reuse the system row's public cover URL. Permanent URLs are never minted for private org assets.", + ) + installed_config_ids: list[str] = Field( + ..., + description="Config IDs (`cfg_...`) of this Solution's installations in the viewer's organization. The array is empty when the Solution is visible only from the system catalog.", + ) + kind: str = Field(..., description='Resource type. Always `"Solution"`.') + latest_solution: str | None = Field( + default=None, + description="When `upgrade_available` is `true`, the system-scope Solution config ID (`cfg_...`) that should be used as the upgrade source. `null` otherwise.", + ) + latest_version: str | None = Field( + default=None, + description="When `upgrade_available` is `true`, the higher system-scope `solution_version` available to upgrade to. `null` otherwise.", + ) + lookup_key: str | None = Field( + default=None, + description="The lookup key stored on the Solution config, if one was assigned during import. `null` when no lookup key was set.", + ) + metadata: dict[str, Any] | None = Field( + default=None, + description="Arbitrary key-value metadata declared in the Solution body (e.g. category or display hints). Present as an empty object when the body declares none.", + ) + name: str | None = Field( + default=None, + description="Human-facing display name declared in the Solution body. `null` when the Solution body does not set one.", + ) + org: str | None = Field( + default=None, + description="Organization ID (`org_...`) that owns this Solution config, when the Solution is scoped to a specific org. `null` for system-scope (app-level) Solutions.", + ) + org_logo: ( + OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionSolutionOrgLogo | None + ) = Field( + default=None, + description="Canonical image-source object for the resolved `org`'s logo, used as the principal category section glyph. The `url` is a stable, non-expiring capability URL (`refresh_url` is `null` there is nothing to refresh). `null` when `org_slug` is `null` or the org has no logo.", + ) + org_name: str | None = Field( + default=None, + description="Display name of the resolved `org`. Pairs with `org_slug` as the principal catalog category's label. `null` when `org_slug` is `null`.", + ) + org_slug: str | None = Field( + default=None, + description="Resolved slug of the Solution body's `org` (the publishing organization), when set and it resolves to a real org visible to the viewer. When present this is the Solution's principal catalog category key clients group the Solution under this org ahead of `category_keys`. `null` when the body has no `org` or it doesn't resolve.", + ) + owners: list[str] = Field( + ..., + description='Owner scopes this Solution appears under. Members: `"system"` (app-level system scope) and/or `"org"` (viewer\'s org scope).', + ) + readme_url: str | None = Field( + default=None, + description="Relative path to the public README endpoint with a signed token already embedded. `null` when the Solution has no README. Token expires in 1 hour refresh via `GET /api/v1/solutions/:solution`.", + ) + screenshot_urls: list[str] | None = Field( + default=None, + description="Absolute URLs of the Solution's gallery screenshots the bundled assets the body's `screenshots:` field names, in declared order. Each is a stable, non-expiring capability URL with the same cacheability contract as `image_url` (one shared token, a `v` cache key, and a `file` param selecting the screenshot); a URL 404s if the Solution stops declaring its screenshot. An empty array when the Solution declares none, and always empty for org-scoped rows the permanent URLs are minted for system-scope (catalog) Solutions only.", + ) + solution_id: str | None = Field( + default=None, + description="Stable UUID declared in the Solution body, used to identify the same logical Solution across multiple installed copies and owner scopes. `null` when the body omits it.", + ) + solution_version: str | None = Field( + default=None, + description='Semver string declared in the Solution body (e.g. `"1.2.0"`). `null` when the body does not declare a version.', + ) + tag_keys: list[str] | None = Field( + default=None, + description="Freeform tag keys declared in the Solution body. An empty array when the body declares none.", + ) + template_kind: str | None = Field( + default=None, + description='Wrapped template kind `"AgentTemplate"`, `"AutomationTemplate"`, `"AgentRoutineTemplate"`, `"AgentToolTemplate"`, `"AgentComputerTemplate"`, or `"SolutionTemplateRef"` for ref-mode bundles.', + ) + templates: list[ + OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionSolutionTemplatesItem + ] = Field( + ..., + description="Template configs bundled by this Solution, in declaration order the first entry is the deployable template the Solution wraps; the rest are sibling templates the wrapped template references.", + ) + updated_at: str | None = Field( + default=None, description="When the Solution config was last modified (ISO 8601)." + ) + upgrade_available: bool = Field( + ..., + description="`true` when this Solution is installed at the viewer's org scope and the app-level system scope carries a higher `solution_version`. Always `false` for system-only rows.", + ) + virtual_path: str | None = Field( + default=None, + description="The stable virtual path assigned to this Solution config, used as the deduplication key when the same Solution appears under multiple owner scopes. `null` when unset.", + ) + + +class OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionTemplate(BaseModel): + created_at: datetime | None = Field( + default=None, description="When this template config was created (ISO 8601)." + ) + description: str | None = Field( + default=None, + description="Description of the template from the config body. `null` if the current version has no `description` field.", + ) + display_name: str | None = Field( + default=None, + description="Human-readable display name from the config body. `null` if the current version has no `display_name` field.", + ) + id: str = Field(..., description="Template config ID (`cfg_...`).") + kind: str = Field( + ..., description='Config kind identifier for this template (e.g. `"agent_tool_template"`).' + ) + lookup_key: str | None = Field( + default=None, + description="Stable lookup key assigned to this template config. `null` if no lookup key is set.", + ) + name: str | None = Field( + default=None, + description="Template name as stored in the config body. `null` if the current version has no `name` field.", + ) + updated_at: datetime | None = Field( + default=None, description="When this template config was last modified (ISO 8601)." + ) + virtual_path: str | None = Field( + default=None, + description="Virtual filesystem path for this template config. `null` if not set.", + ) + + +class OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolution(BaseModel): + current_solution: ( + OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionCurrentSolution | None + ) = Field( + default=None, + description="Summary of the current parent Solution config row. `solution` is the pinned Solution version the agent points at; `current_solution` is the source Solution config row as it exists now.", + ) + solution: OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionSolution = Field( + ..., + description="Summary of the parent Solution, including `upgrade_available`, `latest_version`, and `latest_solution` when a newer system-scoped version is available for the agent's org-scoped Solution.", + ) + template: OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolutionTemplate = Field( + ..., + description="Summary of the AgentTemplate config (`cfg_...`) the agent was last provisioned or updated from.", + ) + + +class OrgThreadListResponseDataItemParticipatingAgentsItem(BaseModel): + acl: OrgThreadListResponseDataItemParticipatingAgentsItemAcl | None = Field( + default=None, + description="Access control list for the agent. Contains a `grants` array where each entry specifies `principal_type`, `principal`, and `actions`. `null` when no ACL restrictions are applied and the agent is accessible to all members of its scope.", + ) + app: str | None = Field( + default=None, description="ID of the application that owns this agent (`dap_...`)." + ) + created_at: str | None = Field( + default=None, description="When the agent was created (ISO 8601)." + ) + default_model: str | None = Field( + default=None, + description='Default LLM model identifier used by this agent when no model is specified at runtime (e.g. `"claude-3-7-sonnet-latest"`).', + ) + description: str | None = Field( + default=None, + description="Human-readable description of what the agent does. `null` if not set.", + ) + email: str | None = Field( + default=None, + description="Email address provisioned for this agent. `null` if email delivery is not configured.", + ) + id: str = Field(..., description="Agent ID (`agi_...`).") + identity: str | None = Field( + default=None, + description="System-level identity prompt that shapes the agent's persona and behavior.", + ) + last_applied_template_config: str | None = Field( + default=None, + description="ID of the AgentTemplate config (`cfg_...`) this agent was last provisioned or updated from. `null` for manually created agents.", + ) + lookup_key: str | None = Field( + default=None, + description="Stable, user-defined identifier for this agent within the application. Unique per app.", + ) + metadata: dict[str, Any] | None = Field( + default=None, + description="Arbitrary key-value metadata attached to the agent. Not interpreted by the platform.", + ) + name: str | None = Field( + default=None, description="Human-readable display name for the agent. `null` if not set." + ) + org: str | None = Field( + default=None, + description="ID of the organization this agent belongs to (`org_...`). `null` if the agent is not org-scoped.", + ) + org_name: str | None = Field( + default=None, + description="Display name of the organization this agent belongs to. `null` when the agent is not org-scoped or when the org association was not preloaded.", + ) + originator: str | None = Field( + default=None, + description="Free-form label identifying the source or author that created this agent (e.g. a username or pipeline name).", + ) + phone_number: str | None = Field( + default=None, + description="Phone number provisioned for this agent. `null` if SMS is not configured.", + ) + sandbox: str | None = Field( + default=None, + description="ID of the sandbox environment this agent is scoped to (`dsb_...`). `null` in production deployments.", + ) + source_solution: OrgThreadListResponseDataItemParticipatingAgentsItemSourceSolution | None = ( + Field( + default=None, + description="Source Solution and AgentTemplate summary for agents provisioned from a Solution. Includes `upgrade_available`, `latest_version`, and `latest_solution` so you can render an upgrade badge without a separate dry-run call. `null` for hand-built agents and agents whose tracked template or parent Solution has been deleted. Populated only on single-agent GET responses, never on list endpoints.", + ) + ) + team: str | None = Field( + default=None, + description="ID of the team that owns this agent (`tem_...`). `null` if the agent is not team-scoped.", + ) + template_upgrade_available: bool | None = Field( + default=None, + description="True when the agent's last-applied template version is behind the current version of its AgentTemplate config i.e. reapplying the template (a per-agent upgrade) would bring it newer Solution content. Self-clears once the agent is reapplied. Computed on both the list endpoints and single-agent GET. Distinct from `source_solution.upgrade_available`, which compares Solution *versions*: an agent can lag its template (`template_upgrade_available: true`) while the org already holds the latest Solution version (`upgrade_available: false`).", + ) + updated_at: str | None = Field( + default=None, description="When the agent was last modified (ISO 8601)." + ) + user: str | None = Field( + default=None, + description="ID of the user that owns this agent (`usr_...`). `null` if the agent is not user-scoped.", + ) + + +class OrgThreadListResponseDataItemSettings(BaseModel): + agent_enabled: bool | None = Field( + default=None, + description="Whether the AI agent is active for this thread. `true` enables AI responses; `false` disables them. Defaults to `true` when settings have not been explicitly configured. `null` when a client explicitly cleared the setting.", + ) + + +class OrgThreadListResponseDataItem(BaseModel): + agent_user: str | None = Field( + default=None, + description="ID of the agent that owns this thread (`agt_...`). `null` for user-owned or team-owned threads.", + ) + created_at: str | None = Field( + default=None, description="When the thread was created (ISO 8601)." + ) + creator: str | dict[str, Any] | None = Field( + default=None, + description="User who created this thread. Returns a user ID (`usr_...`) by default, or an expanded user object when the association is loaded. `null` if the creator is unknown.", + ) + description: str | None = Field( + default=None, + description="Optional description or purpose statement for the thread. `null` if not set.", + ) + id: str = Field(..., description="Thread ID (`thr_...`).") + is_channel: bool | None = Field( + default=None, + description="Whether this thread operates as a channel a multi-member broadcast-style conversation.", + ) + is_default: bool | None = Field( + default=None, + description="Whether this is the default thread for its owner. Each user or team has at most one default thread.", + ) + is_transient: bool | None = Field( + default=None, + description="Whether this thread is ephemeral and may be deleted automatically after a period of inactivity or when its TTL expires.", + ) + is_unlisted: bool | None = Field( + default=None, + description="Whether this thread is hidden from public discovery. Unlisted threads are accessible only to direct participants.", + ) + key: str | None = Field( + default=None, + description="Application-defined stable key that uniquely identifies the thread within its scope. Useful for idempotent creation. `null` if not set.", + ) + kind: str | None = Field( + default=None, + description='Thread subtype: `"standard"` for ordinary threads, `"personal"` for a user-and-owned-agents roster, `"feed"` for a post feed with inline replies, `"slack_mirror"` for the membership-strict mirror of a Slack channel, or `"slashwork_mirror"` for the membership-strict mirror of a Slashwork group. `personal` and `feed` are explicit creation options; mirror kinds are server-derived.', + ) + last_activity: str | None = Field( + default=None, + description="When the most recent message was posted in this thread, falling back to the thread's creation time if it has no messages. Always populated on thread list endpoints (which order by it, after default threads); `null` on endpoints that don't compute activity enrichment.", + ) + last_message_preview: str | None = Field( + default=None, + description="Single-line snippet of the most recent message's text content (first non-empty line, truncated to 140 characters). Populated on thread list endpoints alongside `last_activity`; `null` when the thread has no messages, the latest message has no text content (e.g. attachment-only), or the endpoint doesn't compute activity enrichment.", + ) + last_message_sender: str | None = Field( + default=None, + description="Display name of the sender of the most recent message the same message `last_message_preview` snippets. Populated on thread list endpoints; `null` when the thread has no messages or the endpoint doesn't compute activity enrichment.", + ) + metadata: dict[str, Any] | None = Field( + default=None, + description="Arbitrary key-value metadata attached to the thread. Shape is application-defined; `null` if no metadata has been set.", + ) + muted: bool | None = Field( + default=None, + description="Whether the authenticated user has muted notifications for this thread. `true` suppresses all notification delivery.", + ) + org: str | None = Field( + default=None, + description="ID of the organization this thread belongs to (`org_...`). `null` for threads outside an org context.", + ) + parent_message: OrgThreadListResponseDataItemParentMessage | None = Field( + default=None, + description="The message that spawned this thread as a sub-thread. `null` for top-level threads.", + ) + participant: list[str] | None = Field( + default=None, + description="Array of participant user IDs (`usr_...`) who are members of this thread.", + ) + participants: list[OrgThreadListResponseDataItemParticipantsItem] | None = Field( + default=None, + description="Expanded participant user objects for each member of this thread. Populated only when the association is loaded.", + ) + participating_actor: list[str] | None = Field( + default=None, + description="Composite actor identifiers for all participants currently active in this thread. Present only when actor enrichment is requested.", + ) + participating_agents: list[OrgThreadListResponseDataItemParticipatingAgentsItem] | None = Field( + default=None, + description="Expanded agent objects for all agents participating in this thread. Present only when agent enrichment is requested.", + ) + role: str | None = Field( + default=None, + description='The authenticated user\'s membership role in this thread, e.g. `"owner"`, `"member"`, or `"viewer"`. `null` if the user is not a member.', + ) + sandbox: str | None = Field( + default=None, + description="ID of the developer sandbox this thread is scoped to (`dsb_...`). `null` for production threads.", + ) + settings: OrgThreadListResponseDataItemSettings | None = Field( + default=None, + description="Per-thread configuration settings controlling AI agent behavior for this thread.", + ) + slug: str | None = Field( + default=None, + description="URL-safe slug for the thread, used in human-readable permalinks. `null` if not assigned.", + ) + sub_threads: list[dict[str, Any]] | None = Field( + default=None, + description="Threads that are nested under this thread as replies to a parent message. Present only when sub-thread enrichment is requested.", + ) + tags: list[str] | None = Field( + default=None, + description='Status tags on the thread (e.g. `"blocked"`, `"needs-review"`). Edited by any thread participant via the `/threads/:thread/tags` endpoints and filterable on the thread list endpoints. Empty array if none set.', + ) + team: str | None = Field( + default=None, + description="ID of the team that owns this thread (`team_...`). `null` for user-owned or agent-owned threads.", + ) + title: str | None = Field( + default=None, + description="Human-readable name of the thread. `null` if no title has been set.", + ) + ttl: str | None = Field( + default=None, + description="Offset-free expiry timestamp after which the thread may be automatically cleaned up. `null` if the thread does not expire.", + ) + unread_count: int | None = Field( + default=None, + description="Number of messages in this thread that the authenticated user has not yet read. Present only when read-state enrichment is requested.", + ) + updated_at: str | None = Field( + default=None, description="When the thread was last modified (ISO 8601)." + ) + user: str | None = Field( + default=None, + description="ID of the user who owns this thread (`usr_...`). `null` for team-owned or agent-owned threads.", + ) + visibility: Literal["team", "restricted", "private", "org"] = Field( + ..., + description="Who can read the thread: `team` for every owning-team member, `restricted` for team-readable threads with an explicit roster, `private` for roster-only access, or `org` for every member of the owning organization.", + ) + + +class OrgThreadListResponse(BaseModel): + """ + Successful response + """ + + data: list[OrgThreadListResponseDataItem] = Field( + ..., description="Array of org-visibility thread objects." + ) class OrgListResponseDataItem(BaseModel): @@ -170,9 +1610,90 @@ class OrgArtifactsResponse(BaseModel): has_more: bool +class OrgLinkedAccountsResponseDataItem(BaseModel): + account_id: str = Field( + ..., description="The service's name for the account: the login, for GitHub." + ) + provider: str = Field( + ..., description='Service the account is on. Currently always `"github"`.' + ) + user: str = Field(..., description="User ID (`usr_...`) the account belongs to.") + + +class OrgLinkedAccountsResponse(BaseModel): + """ + Successful response + """ + + after_cursor: str | None = None + before_cursor: str | None = Field( + default=None, description="Always null; pagination is forward-only." + ) + data: list[OrgLinkedAccountsResponseDataItem] = Field( + ..., description="Linked accounts, by user." + ) + has_more: bool + + +class AsyncOrgThreadResource: + def __init__(self, http: HttpClient): + self._http = http + + async def list(self, org: str, *, key: str | None = None) -> OrgThreadListResponse: + """ + List organization-visibility threads + Returns org-visibility threads for the specified organization. Every member + of the organization can list these threads; they require no team membership. + App-scoped developer tokens for the organization's app can list them too. + + Args: + org: Organization ID (`org_...`) whose org-visibility threads should be listed. + key: Optional exact thread key, for example `archdev-room`. + + Returns: + Successful response + """ + query: dict[str, object] = {} + if key is not None: + query["key"] = key + return await self._http.request( + f"/api/v1/orgs/{org}/threads", + query=query, + response_type=OrgThreadListResponse, + ) + + async def create(self, org: str, input: OrgThreadCreateInput) -> Thread: + """ + Create an organization-visibility thread + Creates a thread owned by the organization rather than a team, user, or agent. + Every member of the organization can read and post without joining. The + authenticated caller must be an organization administrator, or use an + app-scoped developer token for the organization's app. + When `thread.key` is supplied, creation is idempotent: a second call with the + same key returns the existing org-visibility thread instead of inserting a + duplicate. + + Args: + org: Organization ID (`org_...`) whose org-visibility threads should be listed. + input: Request body. + input.skip_welcome_message: When `true`, suppresses the automatic welcome message that is otherwise sent into the thread on creation. Defaults to `false`. + input.thread: Attributes for the new thread. Visibility is forced to `org`. + + Returns: + The organization-visibility thread. + """ + return await self._http.request( + f"/api/v1/orgs/{org}/threads", + method="POST", + body=input, + response_type=Thread, + ) + + class AsyncOrgResource: def __init__(self, http: HttpClient): self._http = http + self.threads = AsyncOrgThreadResource(http) async def list( self, *, search: str | None = None, page: int | None = None, page_size: int | None = None @@ -245,10 +1766,106 @@ async def artifacts( response_type=OrgArtifactsResponse, ) + async def linked_accounts( + self, + org: str, + *, + user: builtins.list[str] | None = None, + limit: int | None = None, + after_cursor: str | None = None, + ) -> OrgLinkedAccountsResponse: + """ + List an organization's linked accounts + Returns the GitHub login each user in the organization signed in with, so + clients can tell that a pull request's author and a Platform user are the + same person. Users who never signed in with GitHub are absent. Any viewer + acting within the organization can list them; other viewers get 404. + Pass `user` to look up specific users instead of listing the whole + organization. Results are ordered by user and paginated forward with + `after_cursor`. + + Args: + org: Organization ID (`org_...`) whose linked accounts should be listed. + user: Up to 100 user IDs (`usr_...`) to look up. Omit to list every user in the organization. Users in the list who are outside the organization or have no linked account are absent. + limit: Maximum accounts returned, from 1 to 100. + after_cursor: Opaque cursor for the next page. + + Returns: + Successful response + """ + query: dict[str, object] = {} + if user is not None: + query["user"] = user + if limit is not None: + query["limit"] = limit + if after_cursor is not None: + query["after_cursor"] = after_cursor + return await self._http.request( + f"/api/v1/orgs/{org}/linked_accounts", + query=query, + response_type=OrgLinkedAccountsResponse, + ) + + +class OrgThreadResource: + def __init__(self, http: SyncHttpClient): + self._http = http + + def list(self, org: str, *, key: str | None = None) -> OrgThreadListResponse: + """ + List organization-visibility threads + Returns org-visibility threads for the specified organization. Every member + of the organization can list these threads; they require no team membership. + App-scoped developer tokens for the organization's app can list them too. + + Args: + org: Organization ID (`org_...`) whose org-visibility threads should be listed. + key: Optional exact thread key, for example `archdev-room`. + + Returns: + Successful response + """ + query: dict[str, object] = {} + if key is not None: + query["key"] = key + return self._http.request( + f"/api/v1/orgs/{org}/threads", + query=query, + response_type=OrgThreadListResponse, + ) + + def create(self, org: str, input: OrgThreadCreateInput) -> Thread: + """ + Create an organization-visibility thread + Creates a thread owned by the organization rather than a team, user, or agent. + Every member of the organization can read and post without joining. The + authenticated caller must be an organization administrator, or use an + app-scoped developer token for the organization's app. + When `thread.key` is supplied, creation is idempotent: a second call with the + same key returns the existing org-visibility thread instead of inserting a + duplicate. + + Args: + org: Organization ID (`org_...`) whose org-visibility threads should be listed. + input: Request body. + input.skip_welcome_message: When `true`, suppresses the automatic welcome message that is otherwise sent into the thread on creation. Defaults to `false`. + input.thread: Attributes for the new thread. Visibility is forced to `org`. + + Returns: + The organization-visibility thread. + """ + return self._http.request( + f"/api/v1/orgs/{org}/threads", + method="POST", + body=input, + response_type=Thread, + ) + class OrgResource: def __init__(self, http: SyncHttpClient): self._http = http + self.threads = OrgThreadResource(http) def list( self, *, search: str | None = None, page: int | None = None, page_size: int | None = None @@ -320,3 +1937,43 @@ def artifacts( query=query, response_type=OrgArtifactsResponse, ) + + def linked_accounts( + self, + org: str, + *, + user: builtins.list[str] | None = None, + limit: int | None = None, + after_cursor: str | None = None, + ) -> OrgLinkedAccountsResponse: + """ + List an organization's linked accounts + Returns the GitHub login each user in the organization signed in with, so + clients can tell that a pull request's author and a Platform user are the + same person. Users who never signed in with GitHub are absent. Any viewer + acting within the organization can list them; other viewers get 404. + Pass `user` to look up specific users instead of listing the whole + organization. Results are ordered by user and paginated forward with + `after_cursor`. + + Args: + org: Organization ID (`org_...`) whose linked accounts should be listed. + user: Up to 100 user IDs (`usr_...`) to look up. Omit to list every user in the organization. Users in the list who are outside the organization or have no linked account are absent. + limit: Maximum accounts returned, from 1 to 100. + after_cursor: Opaque cursor for the next page. + + Returns: + Successful response + """ + query: dict[str, object] = {} + if user is not None: + query["user"] = user + if limit is not None: + query["limit"] = limit + if after_cursor is not None: + query["after_cursor"] = after_cursor + return self._http.request( + f"/api/v1/orgs/{org}/linked_accounts", + query=query, + response_type=OrgLinkedAccountsResponse, + ) diff --git a/src/archastro/platform/v1/resources/tasks.py b/src/archastro/platform/v1/resources/tasks.py index 1621064..83baccf 100644 --- a/src/archastro/platform/v1/resources/tasks.py +++ b/src/archastro/platform/v1/resources/tasks.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: 60b86d22d3a4 +# Content hash: 67016fab74b4 from __future__ import annotations @@ -1406,6 +1406,29 @@ async def list( async def create(self, task: str, input: LinkCreateInput) -> TaskExternalLink: """ Add an external link to a task + Adds an indexed identity without changing the referenced object's ownership or ACL. + For private files, upload with POST /api/v1/files, then pass external_scope=platform, + object_type=file and object_id=fil_.... The reserved platform namespace means the + authenticated current backend/app/sandbox, not a hostname or stored URL. + File attachment requires both task mutation permission and current file read access. + List and reverse lookup omit files that are missing or no longer readable, including + thread-restricted files. Generic identities are not resolved as local files. + GET /api/v1/files/:file rechecks permission and returns a fresh expiring download URL; + never persist that URL as the link identity. Existing signed URLs remain usable until + their expiry. Task activity and replay may retain opaque file IDs, not file metadata, + and confer no file access. + Retain the upload response's file ID if attachment fails and retry the link request. + Detaching or deleting a task does not delete the file. Deleting a file leaves historical + link events intact; replay does not restore bytes or access. No ACL grant is implicit. + Agent-owned uploads use an authorized human session; agent-only file credentials + remain unsupported. + Download URLs depend on the configured storage provider. The development local + provider returns a local URL prefix plus a storage path, but Platform does not + serve that path over HTTP. Local-provider verification reads bytes from the + running Platform's configured storage directory after authorized metadata reads; + it does not prove HTTP download authorization. Serving local downloads through + an authorization-preserving route is a separate follow-up, not a public /storage + mount. Served providers are verified through their HTTP download URLs. Args: task: Task ID (`tsk_...`). @@ -2064,6 +2087,29 @@ def list( def create(self, task: str, input: LinkCreateInput) -> TaskExternalLink: """ Add an external link to a task + Adds an indexed identity without changing the referenced object's ownership or ACL. + For private files, upload with POST /api/v1/files, then pass external_scope=platform, + object_type=file and object_id=fil_.... The reserved platform namespace means the + authenticated current backend/app/sandbox, not a hostname or stored URL. + File attachment requires both task mutation permission and current file read access. + List and reverse lookup omit files that are missing or no longer readable, including + thread-restricted files. Generic identities are not resolved as local files. + GET /api/v1/files/:file rechecks permission and returns a fresh expiring download URL; + never persist that URL as the link identity. Existing signed URLs remain usable until + their expiry. Task activity and replay may retain opaque file IDs, not file metadata, + and confer no file access. + Retain the upload response's file ID if attachment fails and retry the link request. + Detaching or deleting a task does not delete the file. Deleting a file leaves historical + link events intact; replay does not restore bytes or access. No ACL grant is implicit. + Agent-owned uploads use an authorized human session; agent-only file credentials + remain unsupported. + Download URLs depend on the configured storage provider. The development local + provider returns a local URL prefix plus a storage path, but Platform does not + serve that path over HTTP. Local-provider verification reads bytes from the + running Platform's configured storage directory after authorized metadata reads; + it does not prove HTTP download authorization. Serving local downloads through + an authorization-preserving route is a separate follow-up, not a public /storage + mount. Served providers are verified through their HTTP download URLs. Args: task: Task ID (`tsk_...`). diff --git a/src/archastro/platform/v1/resources/teams.py b/src/archastro/platform/v1/resources/teams.py index 6b228f3..1ad227b 100644 --- a/src/archastro/platform/v1/resources/teams.py +++ b/src/archastro/platform/v1/resources/teams.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: aa08841149e3 +# Content hash: 14d31bec228a from __future__ import annotations @@ -13,7 +13,7 @@ from ...runtime.http_client import HttpClient, SyncHttpClient from ...types.common import CustomObject from ...types.tasks import Task -from ...types.teams import Team, TeamInvite, TeamMembership +from ...types.teams import Team, TeamDeleteImpactResponse, TeamInvite, TeamMembership from ...types.threads import Thread @@ -124,8 +124,8 @@ class TeamThreadCreateInputThread(TypedDict, total=False): "When `true`, the thread is hidden from the default thread list and accessible only by direct link or ID." key: str | None "Client-assigned unique key for idempotent creation or later lookup. Must be unique within the owning organization." - kind: Literal["personal"] | None - "Optional behavioral subtype. `personal` is accepted only for a user-owned thread and limits membership to that user and agents currently owned by them. Mirror kinds remain server-derived and cannot be selected by callers." + kind: Literal["personal", "feed"] | None + "Optional behavioral subtype. `personal` is accepted only for a user-owned thread and limits membership to that user and agents currently owned by them. `feed` is accepted for any owner and renders the thread as a post feed: message lists return top-level posts with their newest replies inline, and agent responses attach to the root post. Mirror kinds remain server-derived and cannot be selected by callers." members: list[TeamThreadCreateInputThreadMembersItem] | None "Users and agents to add atomically when the thread is created. Each target must pass the same authorization rules as a post-creation member add. Slack mirror threads reject non-empty caller-supplied rosters because their membership is sync-owned." metadata: dict[str, Any] | None @@ -142,8 +142,8 @@ class TeamThreadCreateInputThread(TypedDict, total=False): "Optional URL-safe identifier. Derived from the title when omitted and unique within the thread owner." title: str | None "Display name for the thread. `null` if omitted, which causes the thread to be untitled." - visibility: Literal["team", "restricted", "private"] | None - "Thread visibility. A team-owned thread with members must explicitly use `restricted` or `private`. User- and agent-owned threads with members default to `private` and reject every other value." + visibility: Literal["team", "restricted", "private", "org"] | None + "Thread visibility. A team-owned thread with members must explicitly use `restricted` or `private`. User- and agent-owned threads with members default to `private` and reject every other value. `org` is only valid on an organization-owned thread with no team, user, or agent owner." class TeamThreadCreateInput(TypedDict, total=False): @@ -2546,6 +2546,10 @@ class TeamThreadListResponseDataItemParentMessageAttachmentsItem(BaseModel): default=None, description="Width in pixels of the scraped preview image. Present on `scraped_link` type only. `null` otherwise.", ) + key: str | None = Field( + default=None, + description='For `structured_data` type, what the data is about as set by the sender (for example `"pr:14963"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.', + ) media_type: str | None = Field( default=None, description='The media category, e.g. `"video"` or `"audio"`. Present on `media` type only; omitted otherwise.', @@ -2556,7 +2560,7 @@ class TeamThreadListResponseDataItemParentMessageAttachmentsItem(BaseModel): ) object: dict[str, Any] | None = Field( default=None, - description="The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types.", + description="The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types.", ) title: str | None = Field( default=None, @@ -2564,7 +2568,7 @@ class TeamThreadListResponseDataItemParentMessageAttachmentsItem(BaseModel): ) type: str = Field( ..., - description='The attachment type. One of `"file"`, `"scraped_link"`, `"artifact"`, `"task"`, `"media"`, `"action"`, or `"chart"`. Determines which additional fields are present.', + description='The attachment type. One of `"file"`, `"scraped_link"`, `"artifact"`, `"task"`, `"media"`, `"action"`, `"chart"`, or `"structured_data"`. Determines which additional fields are present.', ) url: str | None = Field( default=None, @@ -3568,7 +3572,7 @@ class TeamThreadListResponseDataItem(BaseModel): ) kind: str | None = Field( default=None, - description='Thread subtype: `"standard"` for ordinary threads, `"personal"` for a user-and-owned-agents roster, `"slack_mirror"` for the membership-strict mirror of a Slack channel, or `"slashwork_mirror"` for the membership-strict mirror of a Slashwork group. `personal` is an explicit user-thread creation option; mirror kinds are server-derived.', + description='Thread subtype: `"standard"` for ordinary threads, `"personal"` for a user-and-owned-agents roster, `"feed"` for a post feed with inline replies, `"slack_mirror"` for the membership-strict mirror of a Slack channel, or `"slashwork_mirror"` for the membership-strict mirror of a Slashwork group. `personal` and `feed` are explicit creation options; mirror kinds are server-derived.', ) last_activity: str | None = Field( default=None, @@ -3663,9 +3667,9 @@ class TeamThreadListResponseDataItem(BaseModel): default=None, description="ID of the user who owns this thread (`usr_...`). `null` for team-owned or agent-owned threads.", ) - visibility: Literal["team", "restricted", "private"] = Field( + visibility: Literal["team", "restricted", "private", "org"] = Field( ..., - description="Who can read the thread: `team` for every owning-team member, `restricted` for team-readable threads with an explicit roster, or `private` for roster-only access.", + description="Who can read the thread: `team` for every owning-team member, `restricted` for team-readable threads with an explicit roster, `private` for roster-only access, or `org` for every member of the owning organization.", ) @@ -4935,6 +4939,24 @@ async def artifacts( response_type=TeamArtifactsResponse, ) + async def dependents(self, team: str) -> TeamDeleteImpactResponse: + """ + Preview Team deletion impact + Returns the number of stored custom-object rows that deleting this Team will + physically delete. The count includes rows hidden after ordinary soft + deletion. This read-only preview does not delete or restore data. + + Args: + team: Team ID (`team_...`) to inspect. + + Returns: + Stored custom-object rows and the existing physical-deletion contract. + """ + return await self._http.request( + f"/api/v1/teams/{team}/dependents", + response_type=TeamDeleteImpactResponse, + ) + async def invites(self, team: str) -> TeamInvitesResponse: """ Create a team invite (server-to-server) @@ -5949,6 +5971,24 @@ def artifacts( response_type=TeamArtifactsResponse, ) + def dependents(self, team: str) -> TeamDeleteImpactResponse: + """ + Preview Team deletion impact + Returns the number of stored custom-object rows that deleting this Team will + physically delete. The count includes rows hidden after ordinary soft + deletion. This read-only preview does not delete or restore data. + + Args: + team: Team ID (`team_...`) to inspect. + + Returns: + Stored custom-object rows and the existing physical-deletion contract. + """ + return self._http.request( + f"/api/v1/teams/{team}/dependents", + response_type=TeamDeleteImpactResponse, + ) + def invites(self, team: str) -> TeamInvitesResponse: """ Create a team invite (server-to-server) diff --git a/src/archastro/platform/v1/resources/threads.py b/src/archastro/platform/v1/resources/threads.py index 5fbd9bb..18ca810 100644 --- a/src/archastro/platform/v1/resources/threads.py +++ b/src/archastro/platform/v1/resources/threads.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: a0c8f7a7dc6a +# Content hash: 73b7afcbd2f8 from __future__ import annotations @@ -549,6 +549,10 @@ class ThreadMessagesResponseDataMessagesItemAttachmentsItem(BaseModel): default=None, description="Width in pixels of the scraped preview image. Present on `scraped_link` type only. `null` otherwise.", ) + key: str | None = Field( + default=None, + description='For `structured_data` type, what the data is about as set by the sender (for example `"pr:14963"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.', + ) media_type: str | None = Field( default=None, description='The media category, e.g. `"video"` or `"audio"`. Present on `media` type only; omitted otherwise.', @@ -559,7 +563,7 @@ class ThreadMessagesResponseDataMessagesItemAttachmentsItem(BaseModel): ) object: dict[str, Any] | None = Field( default=None, - description="The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types.", + description="The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types.", ) title: str | None = Field( default=None, @@ -567,7 +571,7 @@ class ThreadMessagesResponseDataMessagesItemAttachmentsItem(BaseModel): ) type: str = Field( ..., - description='The attachment type. One of `"file"`, `"scraped_link"`, `"artifact"`, `"task"`, `"media"`, `"action"`, or `"chart"`. Determines which additional fields are present.', + description='The attachment type. One of `"file"`, `"scraped_link"`, `"artifact"`, `"task"`, `"media"`, `"action"`, `"chart"`, or `"structured_data"`. Determines which additional fields are present.', ) url: str | None = Field( default=None, @@ -1248,6 +1252,8 @@ async def messages( The authenticated user must have access to the thread's owner (workspace or user). A 403 is returned if the thread exists but is not accessible to the caller; a 404 is returned if the thread does not exist or is not visible to the authenticated user. + Threads with `kind: feed` return only top-level posts, each with its newest + replies inline under `replies` and reply cursors for paging the rest. Pass `include_reply_counts: true` to annotate each message with the number of threaded replies it has received. This adds a small amount of latency and should be omitted when reply counts are not needed. @@ -1838,6 +1844,8 @@ def messages( The authenticated user must have access to the thread's owner (workspace or user). A 403 is returned if the thread exists but is not accessible to the caller; a 404 is returned if the thread does not exist or is not visible to the authenticated user. + Threads with `kind: feed` return only top-level posts, each with its newest + replies inline under `replies` and reply cursors for paging the rest. Pass `include_reply_counts: true` to annotate each message with the number of threaded replies it has received. This adds a small amount of latency and should be omitted when reply counts are not needed. diff --git a/src/archastro/platform/v1/resources/users.py b/src/archastro/platform/v1/resources/users.py index 99470c6..7d57700 100644 --- a/src/archastro/platform/v1/resources/users.py +++ b/src/archastro/platform/v1/resources/users.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: c897f0ca35c8 +# Content hash: e3a983ce419d from __future__ import annotations @@ -107,8 +107,8 @@ class UserThreadCreateInputThread(TypedDict, total=False): "When `true`, the thread is hidden from the default thread list and accessible only by direct link or ID." key: str | None "Client-assigned unique key for idempotent creation or later lookup. Must be unique within the owning organization." - kind: Literal["personal"] | None - "Optional behavioral subtype. `personal` is accepted only for a user-owned thread and limits membership to that user and agents currently owned by them. Mirror kinds remain server-derived and cannot be selected by callers." + kind: Literal["personal", "feed"] | None + "Optional behavioral subtype. `personal` is accepted only for a user-owned thread and limits membership to that user and agents currently owned by them. `feed` is accepted for any owner and renders the thread as a post feed: message lists return top-level posts with their newest replies inline, and agent responses attach to the root post. Mirror kinds remain server-derived and cannot be selected by callers." members: list[UserThreadCreateInputThreadMembersItem] | None "Users and agents to add atomically when the thread is created. Each target must pass the same authorization rules as a post-creation member add. Slack mirror threads reject non-empty caller-supplied rosters because their membership is sync-owned." metadata: dict[str, Any] | None @@ -125,8 +125,8 @@ class UserThreadCreateInputThread(TypedDict, total=False): "Optional URL-safe identifier. Derived from the title when omitted and unique within the thread owner." title: str | None "Display name for the thread. `null` if omitted, which causes the thread to be untitled." - visibility: Literal["team", "restricted", "private"] | None - "Thread visibility. A team-owned thread with members must explicitly use `restricted` or `private`. User- and agent-owned threads with members default to `private` and reject every other value." + visibility: Literal["team", "restricted", "private", "org"] | None + "Thread visibility. A team-owned thread with members must explicitly use `restricted` or `private`. User- and agent-owned threads with members default to `private` and reject every other value. `org` is only valid on an organization-owned thread with no team, user, or agent owner." class UserThreadCreateInput(TypedDict, total=False): @@ -1511,6 +1511,10 @@ class UserThreadListResponseDataItemParentMessageAttachmentsItem(BaseModel): default=None, description="Width in pixels of the scraped preview image. Present on `scraped_link` type only. `null` otherwise.", ) + key: str | None = Field( + default=None, + description='For `structured_data` type, what the data is about as set by the sender (for example `"pr:14963"`), copied from the record so it can be read without `object`. Not unique. `null` when unset and on other types.', + ) media_type: str | None = Field( default=None, description='The media category, e.g. `"video"` or `"audio"`. Present on `media` type only; omitted otherwise.', @@ -1521,7 +1525,7 @@ class UserThreadListResponseDataItemParentMessageAttachmentsItem(BaseModel): ) object: dict[str, Any] | None = Field( default=None, - description="The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types.", + description="The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. For `structured_data` type, contains the inline `data` and the `schema_url` or `schema_config` naming its JSON Schema. Omitted on other types.", ) title: str | None = Field( default=None, @@ -1529,7 +1533,7 @@ class UserThreadListResponseDataItemParentMessageAttachmentsItem(BaseModel): ) type: str = Field( ..., - description='The attachment type. One of `"file"`, `"scraped_link"`, `"artifact"`, `"task"`, `"media"`, `"action"`, or `"chart"`. Determines which additional fields are present.', + description='The attachment type. One of `"file"`, `"scraped_link"`, `"artifact"`, `"task"`, `"media"`, `"action"`, `"chart"`, or `"structured_data"`. Determines which additional fields are present.', ) url: str | None = Field( default=None, @@ -2533,7 +2537,7 @@ class UserThreadListResponseDataItem(BaseModel): ) kind: str | None = Field( default=None, - description='Thread subtype: `"standard"` for ordinary threads, `"personal"` for a user-and-owned-agents roster, `"slack_mirror"` for the membership-strict mirror of a Slack channel, or `"slashwork_mirror"` for the membership-strict mirror of a Slashwork group. `personal` is an explicit user-thread creation option; mirror kinds are server-derived.', + description='Thread subtype: `"standard"` for ordinary threads, `"personal"` for a user-and-owned-agents roster, `"feed"` for a post feed with inline replies, `"slack_mirror"` for the membership-strict mirror of a Slack channel, or `"slashwork_mirror"` for the membership-strict mirror of a Slashwork group. `personal` and `feed` are explicit creation options; mirror kinds are server-derived.', ) last_activity: str | None = Field( default=None, @@ -2628,9 +2632,9 @@ class UserThreadListResponseDataItem(BaseModel): default=None, description="ID of the user who owns this thread (`usr_...`). `null` for team-owned or agent-owned threads.", ) - visibility: Literal["team", "restricted", "private"] = Field( + visibility: Literal["team", "restricted", "private", "org"] = Field( ..., - description="Who can read the thread: `team` for every owning-team member, `restricted` for team-readable threads with an explicit roster, or `private` for roster-only access.", + description="Who can read the thread: `team` for every owning-team member, `restricted` for team-readable threads with an explicit roster, `private` for roster-only access, or `org` for every member of the owning organization.", ) diff --git a/tests/contract/channels/test_api_chat_channel.py b/tests/contract/channels/test_api_chat_channel.py index 8e482c5..78570c1 100644 --- a/tests/contract/channels/test_api_chat_channel.py +++ b/tests/contract/channels/test_api_chat_channel.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: 5df96c308eaf +# Content hash: 3635861564de """ Contract tests for ApiChatChannel — generated from the channel spec. @@ -147,6 +147,41 @@ async def test_api_chat_channel_join_team_transient_surfaces_server_error_reply_ ) +async def test_api_chat_channel_join_org_thread_joins_and_receives_contract_valid_reply(rig): + _, socket = rig + channel = await ApiChatChannel.join_org_thread( + socket, + "test-id", + "test-id", + after_cursor="test-value", + before_cursor="test-value", + include_metadata=True, + limit=1, + ) + assert isinstance(channel, ApiChatChannel) + assert channel.join_response is not None + + +async def test_api_chat_channel_join_org_thread_surfaces_server_error_reply_as_channel_error(rig): + client, socket = rig + await client.register_scenario( + { + "topic": "api:chat:org:test-id:thread:test-id", + "onJoin": [{"type": "replyError", "payload": {"reason": "test_error"}}], + } + ) + with pytest.raises(ChannelError): + await ApiChatChannel.join_org_thread( + socket, + "test-id", + "test-id", + after_cursor="test-value", + before_cursor="test-value", + include_metadata=True, + limit=1, + ) + + async def test_api_chat_channel_join_user_thread_joins_and_receives_contract_valid_reply(rig): _, socket = rig channel = await ApiChatChannel.join_user_thread( diff --git a/tests/contract/v1/test_ai.py b/tests/contract/v1/test_ai.py index 7af3f99..ca98041 100644 --- a/tests/contract/v1/test_ai.py +++ b/tests/contract/v1/test_ai.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: 9b2b00417d06 +# Content hash: ac5f9d33be54 import pytest from pydantic import BaseModel @@ -43,6 +43,90 @@ def _async_error_client(code: int) -> AsyncPlatformClient: ) +def test_ai_session_token_success(): + client = _client() + try: + result = client.v1.ai.session_token({"user_id": "test-id"}) + assert isinstance(result, BaseModel) + assert type(result).__name__ == "AiSessionTokenResponse" + finally: + client.close() + + +def test_ai_session_token_error_401(): + ec = _error_client(401) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.ai.session_token({"user_id": "test-id"}) + assert exc_info.value.status == 401 + finally: + ec.close() + + +def test_ai_session_token_error_403(): + ec = _error_client(403) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.ai.session_token({"user_id": "test-id"}) + assert exc_info.value.status == 403 + finally: + ec.close() + + +def test_ai_session_token_error_422(): + ec = _error_client(422) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.ai.session_token({"user_id": "test-id"}) + assert exc_info.value.status == 422 + finally: + ec.close() + + +@pytest.mark.asyncio +async def test_async_ai_session_token_success(): + client = _async_client() + try: + result = await client.v1.ai.session_token({"user_id": "test-id"}) + assert isinstance(result, BaseModel) + assert type(result).__name__ == "AiSessionTokenResponse" + finally: + await client.close() + + +@pytest.mark.asyncio +async def test_async_ai_session_token_error_401(): + ec = _async_error_client(401) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.ai.session_token({"user_id": "test-id"}) + assert exc_info.value.status == 401 + finally: + await ec.close() + + +@pytest.mark.asyncio +async def test_async_ai_session_token_error_403(): + ec = _async_error_client(403) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.ai.session_token({"user_id": "test-id"}) + assert exc_info.value.status == 403 + finally: + await ec.close() + + +@pytest.mark.asyncio +async def test_async_ai_session_token_error_422(): + ec = _async_error_client(422) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.ai.session_token({"user_id": "test-id"}) + assert exc_info.value.status == 422 + finally: + await ec.close() + + def test_ai_chat_models_success(): client = _client() try: @@ -156,6 +240,18 @@ def test_ai_chat_completions_create_error_402(): ec.close() +def test_ai_chat_completions_create_error_403(): + ec = _error_client(403) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.ai.chat.completions.create( + {"messages": [{"role": "user"}], "opts": {"model": "test-model"}} + ) + assert exc_info.value.status == 403 + finally: + ec.close() + + def test_ai_chat_completions_create_error_422(): ec = _error_client(422) try: @@ -220,6 +316,19 @@ async def test_async_ai_chat_completions_create_error_402(): await ec.close() +@pytest.mark.asyncio +async def test_async_ai_chat_completions_create_error_403(): + ec = _async_error_client(403) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.ai.chat.completions.create( + {"messages": [{"role": "user"}], "opts": {"model": "test-model"}} + ) + assert exc_info.value.status == 403 + finally: + await ec.close() + + @pytest.mark.asyncio async def test_async_ai_chat_completions_create_error_422(): ec = _async_error_client(422) @@ -358,6 +467,277 @@ async def test_async_ai_embedding_similarity_comparison_error_422(): await ec.close() +def test_ai_evaluation_evaluations_success(): + client = _client() + try: + result = client.v1.ai.evaluation.evaluations( + { + "questions": [{"id": "test-id", "instructions": "test-value", "type": "boolean"}], + "state": {}, + } + ) + assert isinstance(result, BaseModel) + assert type(result).__name__ == "AIEvaluationResult" + finally: + client.close() + + +def test_ai_evaluation_evaluations_error_400(): + ec = _error_client(400) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.ai.evaluation.evaluations( + { + "questions": [ + {"id": "test-id", "instructions": "test-value", "type": "boolean"} + ], + "state": {}, + } + ) + assert exc_info.value.status == 400 + finally: + ec.close() + + +def test_ai_evaluation_evaluations_error_401(): + ec = _error_client(401) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.ai.evaluation.evaluations( + { + "questions": [ + {"id": "test-id", "instructions": "test-value", "type": "boolean"} + ], + "state": {}, + } + ) + assert exc_info.value.status == 401 + finally: + ec.close() + + +def test_ai_evaluation_evaluations_error_402(): + ec = _error_client(402) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.ai.evaluation.evaluations( + { + "questions": [ + {"id": "test-id", "instructions": "test-value", "type": "boolean"} + ], + "state": {}, + } + ) + assert exc_info.value.status == 402 + finally: + ec.close() + + +def test_ai_evaluation_evaluations_error_403(): + ec = _error_client(403) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.ai.evaluation.evaluations( + { + "questions": [ + {"id": "test-id", "instructions": "test-value", "type": "boolean"} + ], + "state": {}, + } + ) + assert exc_info.value.status == 403 + finally: + ec.close() + + +def test_ai_evaluation_evaluations_error_422(): + ec = _error_client(422) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.ai.evaluation.evaluations( + { + "questions": [ + {"id": "test-id", "instructions": "test-value", "type": "boolean"} + ], + "state": {}, + } + ) + assert exc_info.value.status == 422 + finally: + ec.close() + + +@pytest.mark.asyncio +async def test_async_ai_evaluation_evaluations_success(): + client = _async_client() + try: + result = await client.v1.ai.evaluation.evaluations( + { + "questions": [{"id": "test-id", "instructions": "test-value", "type": "boolean"}], + "state": {}, + } + ) + assert isinstance(result, BaseModel) + assert type(result).__name__ == "AIEvaluationResult" + finally: + await client.close() + + +@pytest.mark.asyncio +async def test_async_ai_evaluation_evaluations_error_400(): + ec = _async_error_client(400) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.ai.evaluation.evaluations( + { + "questions": [ + {"id": "test-id", "instructions": "test-value", "type": "boolean"} + ], + "state": {}, + } + ) + assert exc_info.value.status == 400 + finally: + await ec.close() + + +@pytest.mark.asyncio +async def test_async_ai_evaluation_evaluations_error_401(): + ec = _async_error_client(401) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.ai.evaluation.evaluations( + { + "questions": [ + {"id": "test-id", "instructions": "test-value", "type": "boolean"} + ], + "state": {}, + } + ) + assert exc_info.value.status == 401 + finally: + await ec.close() + + +@pytest.mark.asyncio +async def test_async_ai_evaluation_evaluations_error_402(): + ec = _async_error_client(402) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.ai.evaluation.evaluations( + { + "questions": [ + {"id": "test-id", "instructions": "test-value", "type": "boolean"} + ], + "state": {}, + } + ) + assert exc_info.value.status == 402 + finally: + await ec.close() + + +@pytest.mark.asyncio +async def test_async_ai_evaluation_evaluations_error_403(): + ec = _async_error_client(403) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.ai.evaluation.evaluations( + { + "questions": [ + {"id": "test-id", "instructions": "test-value", "type": "boolean"} + ], + "state": {}, + } + ) + assert exc_info.value.status == 403 + finally: + await ec.close() + + +@pytest.mark.asyncio +async def test_async_ai_evaluation_evaluations_error_422(): + ec = _async_error_client(422) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.ai.evaluation.evaluations( + { + "questions": [ + {"id": "test-id", "instructions": "test-value", "type": "boolean"} + ], + "state": {}, + } + ) + assert exc_info.value.status == 422 + finally: + await ec.close() + + +def test_ai_evaluation_models_success(): + client = _client() + try: + result = client.v1.ai.evaluation.models() + assert isinstance(result, BaseModel) + assert type(result).__name__ == "EvaluationModelsResponse" + assert isinstance(result.data, list) + finally: + client.close() + + +def test_ai_evaluation_models_error_401(): + ec = _error_client(401) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.ai.evaluation.models() + assert exc_info.value.status == 401 + finally: + ec.close() + + +def test_ai_evaluation_models_error_403(): + ec = _error_client(403) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.ai.evaluation.models() + assert exc_info.value.status == 403 + finally: + ec.close() + + +@pytest.mark.asyncio +async def test_async_ai_evaluation_models_success(): + client = _async_client() + try: + result = await client.v1.ai.evaluation.models() + assert isinstance(result, BaseModel) + assert type(result).__name__ == "EvaluationModelsResponse" + assert isinstance(result.data, list) + finally: + await client.close() + + +@pytest.mark.asyncio +async def test_async_ai_evaluation_models_error_401(): + ec = _async_error_client(401) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.ai.evaluation.models() + assert exc_info.value.status == 401 + finally: + await ec.close() + + +@pytest.mark.asyncio +async def test_async_ai_evaluation_models_error_403(): + ec = _async_error_client(403) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.ai.evaluation.models() + assert exc_info.value.status == 403 + finally: + await ec.close() + + def test_ai_image_edits_success(): client = _client() try: diff --git a/tests/contract/v1/test_config.py b/tests/contract/v1/test_config.py index 8ea46ab..ae137ab 100644 --- a/tests/contract/v1/test_config.py +++ b/tests/contract/v1/test_config.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: 04453714c29f +# Content hash: 81753c1cd826 import pytest from pydantic import BaseModel @@ -168,6 +168,18 @@ def test_config_create_error_422(): ec.close() +def test_config_create_error_503(): + ec = _error_client(503) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.config.create( + {"kind": "test", "mime_type": "application/json", "raw_content": "test content"} + ) + assert exc_info.value.status == 503 + finally: + ec.close() + + @pytest.mark.asyncio async def test_async_config_create_success(): client = _async_client() @@ -233,6 +245,19 @@ async def test_async_config_create_error_422(): await ec.close() +@pytest.mark.asyncio +async def test_async_config_create_error_503(): + ec = _async_error_client(503) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.config.create( + {"kind": "test", "mime_type": "application/json", "raw_content": "test content"} + ) + assert exc_info.value.status == 503 + finally: + await ec.close() + + def test_config_encrypt_secret_success(): client = _client() try: diff --git a/tests/contract/v1/test_custom_objects.py b/tests/contract/v1/test_custom_objects.py index d6c7b67..e03f35f 100644 --- a/tests/contract/v1/test_custom_objects.py +++ b/tests/contract/v1/test_custom_objects.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: 286113bc21e0 +# Content hash: 53db68be181a import pytest from pydantic import BaseModel @@ -419,6 +419,16 @@ def test_custom_objects_replace_error_404(): ec.close() +def test_custom_objects_replace_error_409(): + ec = _error_client(409) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.custom_objects.replace("test-value", {}) + assert exc_info.value.status == 409 + finally: + ec.close() + + def test_custom_objects_replace_error_422(): ec = _error_client(422) try: @@ -473,6 +483,17 @@ async def test_async_custom_objects_replace_error_404(): await ec.close() +@pytest.mark.asyncio +async def test_async_custom_objects_replace_error_409(): + ec = _async_error_client(409) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.custom_objects.replace("test-value", {}) + assert exc_info.value.status == 409 + finally: + await ec.close() + + @pytest.mark.asyncio async def test_async_custom_objects_replace_error_422(): ec = _async_error_client(422) diff --git a/tests/contract/v1/test_orgs.py b/tests/contract/v1/test_orgs.py index 66ddfa2..149ca59 100644 --- a/tests/contract/v1/test_orgs.py +++ b/tests/contract/v1/test_orgs.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: 651467deec13 +# Content hash: 4eed66ef003a import pytest from pydantic import BaseModel @@ -213,3 +213,259 @@ async def test_async_orgs_artifacts_error_404(): assert exc_info.value.status == 404 finally: await ec.close() + + +def test_orgs_linked_accounts_success(): + client = _client() + try: + result = client.v1.orgs.linked_accounts("test-value") + assert isinstance(result, BaseModel) + assert type(result).__name__ == "OrgLinkedAccountsResponse" + assert isinstance(result.data, list) + finally: + client.close() + + +def test_orgs_linked_accounts_error_400(): + ec = _error_client(400) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.orgs.linked_accounts("test-value") + assert exc_info.value.status == 400 + finally: + ec.close() + + +def test_orgs_linked_accounts_error_401(): + ec = _error_client(401) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.orgs.linked_accounts("test-value") + assert exc_info.value.status == 401 + finally: + ec.close() + + +def test_orgs_linked_accounts_error_404(): + ec = _error_client(404) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.orgs.linked_accounts("test-value") + assert exc_info.value.status == 404 + finally: + ec.close() + + +@pytest.mark.asyncio +async def test_async_orgs_linked_accounts_success(): + client = _async_client() + try: + result = await client.v1.orgs.linked_accounts("test-value") + assert isinstance(result, BaseModel) + assert type(result).__name__ == "OrgLinkedAccountsResponse" + assert isinstance(result.data, list) + finally: + await client.close() + + +@pytest.mark.asyncio +async def test_async_orgs_linked_accounts_error_400(): + ec = _async_error_client(400) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.orgs.linked_accounts("test-value") + assert exc_info.value.status == 400 + finally: + await ec.close() + + +@pytest.mark.asyncio +async def test_async_orgs_linked_accounts_error_401(): + ec = _async_error_client(401) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.orgs.linked_accounts("test-value") + assert exc_info.value.status == 401 + finally: + await ec.close() + + +@pytest.mark.asyncio +async def test_async_orgs_linked_accounts_error_404(): + ec = _async_error_client(404) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.orgs.linked_accounts("test-value") + assert exc_info.value.status == 404 + finally: + await ec.close() + + +def test_orgs_threads_list_success(): + client = _client() + try: + result = client.v1.orgs.threads.list("test-value") + assert isinstance(result, BaseModel) + assert type(result).__name__ == "OrgThreadListResponse" + assert isinstance(result.data, list) + finally: + client.close() + + +def test_orgs_threads_list_error_401(): + ec = _error_client(401) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.orgs.threads.list("test-value") + assert exc_info.value.status == 401 + finally: + ec.close() + + +def test_orgs_threads_list_error_404(): + ec = _error_client(404) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.orgs.threads.list("test-value") + assert exc_info.value.status == 404 + finally: + ec.close() + + +@pytest.mark.asyncio +async def test_async_orgs_threads_list_success(): + client = _async_client() + try: + result = await client.v1.orgs.threads.list("test-value") + assert isinstance(result, BaseModel) + assert type(result).__name__ == "OrgThreadListResponse" + assert isinstance(result.data, list) + finally: + await client.close() + + +@pytest.mark.asyncio +async def test_async_orgs_threads_list_error_401(): + ec = _async_error_client(401) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.orgs.threads.list("test-value") + assert exc_info.value.status == 401 + finally: + await ec.close() + + +@pytest.mark.asyncio +async def test_async_orgs_threads_list_error_404(): + ec = _async_error_client(404) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.orgs.threads.list("test-value") + assert exc_info.value.status == 404 + finally: + await ec.close() + + +def test_orgs_threads_create_success(): + client = _client() + try: + result = client.v1.orgs.threads.create("test-value", {"thread": {}}) + assert isinstance(result, BaseModel) + assert type(result).__name__ == "Thread" + finally: + client.close() + + +def test_orgs_threads_create_error_401(): + ec = _error_client(401) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.orgs.threads.create("test-value", {"thread": {}}) + assert exc_info.value.status == 401 + finally: + ec.close() + + +def test_orgs_threads_create_error_403(): + ec = _error_client(403) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.orgs.threads.create("test-value", {"thread": {}}) + assert exc_info.value.status == 403 + finally: + ec.close() + + +def test_orgs_threads_create_error_404(): + ec = _error_client(404) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.orgs.threads.create("test-value", {"thread": {}}) + assert exc_info.value.status == 404 + finally: + ec.close() + + +def test_orgs_threads_create_error_422(): + ec = _error_client(422) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.orgs.threads.create("test-value", {"thread": {}}) + assert exc_info.value.status == 422 + finally: + ec.close() + + +@pytest.mark.asyncio +async def test_async_orgs_threads_create_success(): + client = _async_client() + try: + result = await client.v1.orgs.threads.create("test-value", {"thread": {}}) + assert isinstance(result, BaseModel) + assert type(result).__name__ == "Thread" + finally: + await client.close() + + +@pytest.mark.asyncio +async def test_async_orgs_threads_create_error_401(): + ec = _async_error_client(401) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.orgs.threads.create("test-value", {"thread": {}}) + assert exc_info.value.status == 401 + finally: + await ec.close() + + +@pytest.mark.asyncio +async def test_async_orgs_threads_create_error_403(): + ec = _async_error_client(403) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.orgs.threads.create("test-value", {"thread": {}}) + assert exc_info.value.status == 403 + finally: + await ec.close() + + +@pytest.mark.asyncio +async def test_async_orgs_threads_create_error_404(): + ec = _async_error_client(404) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.orgs.threads.create("test-value", {"thread": {}}) + assert exc_info.value.status == 404 + finally: + await ec.close() + + +@pytest.mark.asyncio +async def test_async_orgs_threads_create_error_422(): + ec = _async_error_client(422) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.orgs.threads.create("test-value", {"thread": {}}) + assert exc_info.value.status == 422 + finally: + await ec.close() diff --git a/tests/contract/v1/test_teams.py b/tests/contract/v1/test_teams.py index 0613257..83b2f13 100644 --- a/tests/contract/v1/test_teams.py +++ b/tests/contract/v1/test_teams.py @@ -1,6 +1,6 @@ # Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. # This file is auto-generated by @archastro/sdk-generator. Do not edit. -# Content hash: ee5ab8a6f480 +# Content hash: f9b2f9040855 import pytest from pydantic import BaseModel @@ -675,6 +675,90 @@ async def test_async_teams_artifacts_error_404(): await ec.close() +def test_teams_dependents_success(): + client = _client() + try: + result = client.v1.teams.dependents("test-value") + assert isinstance(result, BaseModel) + assert type(result).__name__ == "TeamDeleteImpactResponse" + finally: + client.close() + + +def test_teams_dependents_error_401(): + ec = _error_client(401) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.teams.dependents("test-value") + assert exc_info.value.status == 401 + finally: + ec.close() + + +def test_teams_dependents_error_403(): + ec = _error_client(403) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.teams.dependents("test-value") + assert exc_info.value.status == 403 + finally: + ec.close() + + +def test_teams_dependents_error_404(): + ec = _error_client(404) + try: + with pytest.raises(ApiError) as exc_info: + ec.v1.teams.dependents("test-value") + assert exc_info.value.status == 404 + finally: + ec.close() + + +@pytest.mark.asyncio +async def test_async_teams_dependents_success(): + client = _async_client() + try: + result = await client.v1.teams.dependents("test-value") + assert isinstance(result, BaseModel) + assert type(result).__name__ == "TeamDeleteImpactResponse" + finally: + await client.close() + + +@pytest.mark.asyncio +async def test_async_teams_dependents_error_401(): + ec = _async_error_client(401) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.teams.dependents("test-value") + assert exc_info.value.status == 401 + finally: + await ec.close() + + +@pytest.mark.asyncio +async def test_async_teams_dependents_error_403(): + ec = _async_error_client(403) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.teams.dependents("test-value") + assert exc_info.value.status == 403 + finally: + await ec.close() + + +@pytest.mark.asyncio +async def test_async_teams_dependents_error_404(): + ec = _async_error_client(404) + try: + with pytest.raises(ApiError) as exc_info: + await ec.v1.teams.dependents("test-value") + assert exc_info.value.status == 404 + finally: + await ec.close() + + def test_teams_invites_success(): client = _client() try: