archastro.platform.v1.resources.threads
1# Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License. 2# This file is auto-generated by @archastro/sdk-generator. Do not edit. 3# Content hash: 8d947a8b5d00 4 5from __future__ import annotations 6 7from datetime import datetime 8from typing import Any, Literal, Required, TypedDict 9 10from pydantic import BaseModel, Field 11 12from ...runtime.http_client import HttpClient, SyncHttpClient 13from ...types.chat import ChatMember 14from ...types.threads import Thread, ThreadReadStatus, ThreadSettings 15 16 17class ThreadMemberCreateInput(TypedDict, total=False): 18 "Add a member to a thread" 19 20 agent: str | None 21 'Agent ID of the principal to add. Required when `type` is `"agent"`.' 22 membership_type: str | None 23 'Role granted to the new member. One of `"owner"` or `"member"`. Defaults to `"member"`.' 24 type: Required[str] 25 'Kind of principal being added. Must be `"user"` or `"agent"`.' 26 user: str | None 27 'User ID of the principal to add. Required when `type` is `"user"`.' 28 29 30class SettingReplaceInput(TypedDict): 31 "Update thread settings" 32 33 settings: dict[str, Any] 34 "Map of settings fields to update. Include only the keys you want to change." 35 36 37class TagCreateInput(TypedDict): 38 "Add tags to a thread" 39 40 tags: list[str] 41 "Tags to add to the thread." 42 43 44class TagReplaceInput(TypedDict): 45 "Replace a thread's tags" 46 47 tags: list[str] 48 "The complete set of tags for the thread. An empty array clears all tags." 49 50 51class ThreadReplaceInputProfilePicture(TypedDict, total=False): 52 data: str | None 53 "Base64-encoded image payload. Must be a valid base64 string." 54 filename: str | None 55 'Original filename of the image, e.g. `"avatar.png"`. Used for storage metadata.' 56 mime_type: str | None 57 'MIME type of the image, e.g. `"image/jpeg"` or `"image/png"`.' 58 59 60class ThreadReplaceInput(TypedDict, total=False): 61 "Update a thread" 62 63 description: str | None 64 "Optional longer text describing the thread's purpose. Replaces the existing description when provided." 65 metadata: dict[str, Any] | None 66 "Arbitrary key-value metadata to store on the thread. Merged with or replaces existing metadata." 67 muted: bool | None 68 "When `true`, suppresses notifications for new messages in this thread for the authenticated user." 69 profile_picture: ThreadReplaceInputProfilePicture | None 70 "New profile picture for the thread. Provide all three inner fields to replace the existing image." 71 title: str | None 72 "Human-readable display name for the thread. Replaces the existing title when provided." 73 visibility: Literal["private", "restricted", "team"] | None 74 "Widen a team-owned thread: `private` may become `restricted` or `team`, and `restricted` may become `team`. Visibility cannot be narrowed." 75 76 77class ThreadMarkReadInput(TypedDict, total=False): 78 "Mark a thread as read" 79 80 last_read_message: str | None 81 "Message ID (`msg_...`) to record as the last read message. Mutually exclusive with `use_latest_message`." 82 use_latest_message: bool | None 83 "When `true`, marks the thread as read up to the latest message. Mutually exclusive with `last_read_message`." 84 user: str | None 85 "User ID (`usr_...`) whose read state to update. Required for S2S requests; ignored when an authenticated user is present in the token." 86 87 88class ThreadPictureInputPicture(TypedDict): 89 data: str 90 "Base64-encoded binary content of the image file." 91 filename: str 92 'Original filename of the image, e.g. `"avatar.png"`. Used for storage and display.' 93 mime_type: str 94 'MIME type of the image, e.g. `"image/jpeg"` or `"image/png"`.' 95 96 97class ThreadPictureInput(TypedDict): 98 "Update a thread's profile picture" 99 100 picture: ThreadPictureInputPicture 101 "Profile picture payload. Must include the base64-encoded image data and its MIME type." 102 103 104class ThreadMemberListResponseDataItemAgent(BaseModel): 105 email: str | None = Field( 106 default=None, description="Agent email address. `null` if not configured." 107 ) 108 id: str = Field(..., description="Agent ID (`agi_...`).") 109 name: str | None = Field( 110 default=None, description="Human-readable agent name. `null` if not set." 111 ) 112 org: str | None = Field( 113 default=None, 114 description="Organization that owns this agent (`org_...`). `null` if not org-scoped.", 115 ) 116 team: str | None = Field( 117 default=None, 118 description="Team that owns this agent (`tem_...`). `null` if not team-scoped.", 119 ) 120 user: str | None = Field( 121 default=None, 122 description="User that owns this agent (`usr_...`). `null` if not user-scoped.", 123 ) 124 125 126class ThreadMemberListResponseDataItemUser(BaseModel): 127 email: str | None = Field(default=None, description="User's email address. `null` if not set.") 128 full_name: str | None = Field( 129 default=None, description="Backward-compatible alias of `name`. `null` if not set." 130 ) 131 id: str = Field(..., description="User ID (`usr_...`).") 132 name: str | None = Field( 133 default=None, description="Full display name of the user. `null` if not set." 134 ) 135 org: str | None = Field( 136 default=None, 137 description="Organization this user belongs to (`org_...`). `null` if the user is not org-scoped.", 138 ) 139 140 141class ThreadMemberListResponseDataItem(BaseModel): 142 agent: ThreadMemberListResponseDataItemAgent | None = Field( 143 default=None, 144 description="Roster-safe agent identity. Populated for agent members; `null` for users.", 145 ) 146 joined_at: datetime | None = Field( 147 default=None, description="When this member joined the thread (ISO 8601)." 148 ) 149 member_type: str | None = Field( 150 default=None, description="Backward-compatible alias of `type`." 151 ) 152 membership_type: str | None = Field( 153 default=None, description='Role of this member, commonly `"owner"` or `"member"`.' 154 ) 155 role: str | None = Field( 156 default=None, description="Backward-compatible alias of `membership_type`." 157 ) 158 type: str = Field(..., description='Kind of participant. One of `"user"` or `"agent"`.') 159 user: ThreadMemberListResponseDataItemUser | None = Field( 160 default=None, 161 description="Roster-safe user identity. Populated for user members; `null` for agents.", 162 ) 163 164 165class ThreadMemberListResponse(BaseModel): 166 """ 167 Successful response 168 """ 169 170 data: list[ThreadMemberListResponseDataItem] = Field( 171 ..., 172 description="Array of thread member objects representing all current members of the thread.", 173 ) 174 175 176class SettingListResponse(BaseModel): 177 """ 178 Successful response 179 """ 180 181 agent_enabled: bool | None = Field( 182 default=None, 183 description="Whether the AI agent is active for this thread. Defaults to `true` when no settings have been explicitly set.", 184 ) 185 186 187class ThreadAgentsResponse(BaseModel): 188 """ 189 Successful response 190 """ 191 192 data: list[dict[str, Any]] = Field( 193 ..., 194 description="Array of agent objects for the thread. Each object includes `id`, `name`, `alias`, `profile_picture`, and `metadata`. Thread owners also receive an `agent_config` object with the agent's policy type and context configuration.", 195 ) 196 197 198class ThreadArtifactsResponseDataItemImageSource(BaseModel): 199 file: str | None = Field( 200 default=None, 201 description="ID of the underlying storage file (`fil_...`). `null` when the image is not backed by a platform storage file.", 202 ) 203 height: int | None = Field( 204 default=None, description="Height of the image in pixels. `null` if not known." 205 ) 206 media: str | None = Field( 207 default=None, 208 description="ID of the associated media record (`med_...`). `null` when the image is not linked to a media entity.", 209 ) 210 mime_type: str | None = Field( 211 default=None, 212 description='MIME type of the image, e.g. `"image/png"` or `"image/jpeg"`. `null` if not known.', 213 ) 214 refresh_url: str | None = Field( 215 default=None, 216 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.", 217 ) 218 url: str | None = Field( 219 default=None, 220 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.", 221 ) 222 width: int | None = Field( 223 default=None, description="Width of the image in pixels. `null` if not known." 224 ) 225 226 227class ThreadArtifactsResponseDataItem(BaseModel): 228 agent: str | None = Field( 229 default=None, 230 description="ID of the agent that produced this artifact (`agt_...`). `null` if not agent-produced.", 231 ) 232 content_type: str | None = Field( 233 default=None, 234 description='MIME type of the current version\'s file, e.g. `"text/csv"` or `"image/png"`. `null` if no file is attached.', 235 ) 236 created_at: datetime | None = Field( 237 default=None, description="When the artifact was first created (ISO 8601)." 238 ) 239 current_version: str | None = Field( 240 default=None, 241 description="ID of the current (latest published) artifact version (`artv_...`). `null` if no version has been published.", 242 ) 243 description: str | None = Field( 244 default=None, 245 description="Optional longer description of the artifact's contents or purpose. `null` if not set.", 246 ) 247 file: str | None = Field( 248 default=None, 249 description="Storage file ID for the current version (`fil_...`). `null` if no file is attached.", 250 ) 251 file_name: str | None = Field( 252 default=None, 253 description='Original filename of the current version\'s file, e.g. `"output.csv"`. `null` if no file is attached.', 254 ) 255 file_url: str | None = Field( 256 default=None, 257 description="Short-lived signed URL for downloading the current version's file. `null` if no file is attached.", 258 ) 259 id: str = Field(..., description="Artifact ID (`art_...`).") 260 image_source: ThreadArtifactsResponseDataItemImageSource | None = Field( 261 default=None, 262 description='Image source metadata for rendering the current version\'s file inline. Present only when `content_type` starts with `"image/"`. `null` otherwise.', 263 ) 264 name: str | None = Field( 265 default=None, 266 description='Human-readable name for the artifact, e.g. `"Q2 Report"`. `null` if not set.', 267 ) 268 org: str | None = Field( 269 default=None, description="ID of the organization this artifact belongs to (`org_...`)." 270 ) 271 sandbox: str | None = Field( 272 default=None, 273 description="Identifier of the sandbox environment associated with this artifact. `null` if not sandbox-scoped.", 274 ) 275 team: str | None = Field( 276 default=None, 277 description="ID of the team that owns this artifact (`tea_...`). `null` if not team-scoped.", 278 ) 279 thread: str | None = Field( 280 default=None, 281 description="ID of the thread in which this artifact was created (`thr_...`). `null` if not thread-scoped.", 282 ) 283 updated_at: datetime | None = Field( 284 default=None, description="When the artifact record was last modified (ISO 8601)." 285 ) 286 user: str | None = Field( 287 default=None, 288 description="ID of the user who created this artifact (`usr_...`). `null` if not user-scoped.", 289 ) 290 version: int | None = Field( 291 default=None, 292 description="Current version number of the artifact. Increments each time a new version is published.", 293 ) 294 295 296class ThreadArtifactsResponse(BaseModel): 297 """ 298 Successful response 299 """ 300 301 data: list[ThreadArtifactsResponseDataItem] = Field( 302 ..., description="Array of artifact objects produced during the thread's conversation." 303 ) 304 305 306class ThreadMessagesResponseDataMessagesItemAclAddItem(BaseModel): 307 actions: list[str] = Field( 308 ..., 309 description='Array of action strings the principal is permitted to perform, e.g. `["read", "write"]`. Must contain at least one entry.', 310 ) 311 principal: str | None = Field( 312 default=None, 313 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"`.', 314 ) 315 principal_type: str = Field( 316 ..., 317 description='The kind of principal receiving the grant. One of `"user"`, `"team"`, `"org"`, `"org_role"`, `"agent"`, or `"everyone"`.', 318 ) 319 320 321class ThreadMessagesResponseDataMessagesItemAclGrantsItem(BaseModel): 322 actions: list[str] = Field( 323 ..., 324 description='Array of action strings the principal is permitted to perform, e.g. `["read", "write"]`. Must contain at least one entry.', 325 ) 326 principal: str | None = Field( 327 default=None, 328 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"`.', 329 ) 330 principal_type: str = Field( 331 ..., 332 description='The kind of principal receiving the grant. One of `"user"`, `"team"`, `"org"`, `"org_role"`, `"agent"`, or `"everyone"`.', 333 ) 334 335 336class ThreadMessagesResponseDataMessagesItemAclRemoveItem(BaseModel): 337 principal: str | None = Field( 338 default=None, 339 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"`.', 340 ) 341 principal_type: str = Field( 342 ..., 343 description='The kind of principal to remove. One of `"user"`, `"team"`, `"org"`, `"org_role"`, `"agent"`, or `"everyone"`.', 344 ) 345 346 347class ThreadMessagesResponseDataMessagesItemAcl(BaseModel): 348 add: list[ThreadMessagesResponseDataMessagesItemAclAddItem] | None = Field( 349 default=None, 350 description="Patch mode: grants to add or merge into the existing list. Cannot be combined with `grants`.", 351 ) 352 grants: list[ThreadMessagesResponseDataMessagesItemAclGrantsItem] | None = Field( 353 default=None, 354 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`.", 355 ) 356 remove: list[ThreadMessagesResponseDataMessagesItemAclRemoveItem] | None = Field( 357 default=None, 358 description="Patch mode: principals whose grants should be removed from the existing list. Cannot be combined with `grants`.", 359 ) 360 361 362class ThreadMessagesResponseDataMessagesItemActorsItemProfilePicture(BaseModel): 363 file: str | None = Field( 364 default=None, 365 description="ID of the underlying storage file (`fil_...`). `null` when the image is not backed by a platform storage file.", 366 ) 367 height: int | None = Field( 368 default=None, description="Height of the image in pixels. `null` if not known." 369 ) 370 media: str | None = Field( 371 default=None, 372 description="ID of the associated media record (`med_...`). `null` when the image is not linked to a media entity.", 373 ) 374 mime_type: str | None = Field( 375 default=None, 376 description='MIME type of the image, e.g. `"image/png"` or `"image/jpeg"`. `null` if not known.', 377 ) 378 refresh_url: str | None = Field( 379 default=None, 380 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.", 381 ) 382 url: str | None = Field( 383 default=None, 384 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.", 385 ) 386 width: int | None = Field( 387 default=None, description="Width of the image in pixels. `null` if not known." 388 ) 389 390 391class ThreadMessagesResponseDataMessagesItemActorsItem(BaseModel): 392 alias: str | None = Field( 393 default=None, 394 description="Short handle or alias for the actor, used as an alternate display identifier. `null` if not configured.", 395 ) 396 id: str | None = Field( 397 default=None, 398 description='Composite actor identifier. Format is `"user-<usr_...>"` for human users or `"agent-<agi_...>"` for agents.', 399 ) 400 name: str | None = Field( 401 default=None, 402 description="Display name of the actor shown in the UI. `null` if no name is set.", 403 ) 404 profile_picture: ThreadMessagesResponseDataMessagesItemActorsItemProfilePicture | None = Field( 405 default=None, 406 description="Profile picture for the actor. `null` if the actor has no profile picture.", 407 ) 408 409 410class ThreadMessagesResponseDataMessagesItemAttachmentsItemImageSource(BaseModel): 411 file: str | None = Field( 412 default=None, 413 description="ID of the underlying storage file (`fil_...`). `null` when the image is not backed by a platform storage file.", 414 ) 415 height: int | None = Field( 416 default=None, description="Height of the image in pixels. `null` if not known." 417 ) 418 media: str | None = Field( 419 default=None, 420 description="ID of the associated media record (`med_...`). `null` when the image is not linked to a media entity.", 421 ) 422 mime_type: str | None = Field( 423 default=None, 424 description='MIME type of the image, e.g. `"image/png"` or `"image/jpeg"`. `null` if not known.', 425 ) 426 refresh_url: str | None = Field( 427 default=None, 428 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.", 429 ) 430 url: str | None = Field( 431 default=None, 432 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.", 433 ) 434 width: int | None = Field( 435 default=None, description="Width of the image in pixels. `null` if not known." 436 ) 437 438 439class ThreadMessagesResponseDataMessagesItemAttachmentsItemVariantsItemImageSource(BaseModel): 440 file: str | None = Field( 441 default=None, 442 description="ID of the underlying storage file (`fil_...`). `null` when the image is not backed by a platform storage file.", 443 ) 444 height: int | None = Field( 445 default=None, description="Height of the image in pixels. `null` if not known." 446 ) 447 media: str | None = Field( 448 default=None, 449 description="ID of the associated media record (`med_...`). `null` when the image is not linked to a media entity.", 450 ) 451 mime_type: str | None = Field( 452 default=None, 453 description='MIME type of the image, e.g. `"image/png"` or `"image/jpeg"`. `null` if not known.', 454 ) 455 refresh_url: str | None = Field( 456 default=None, 457 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.", 458 ) 459 url: str | None = Field( 460 default=None, 461 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.", 462 ) 463 width: int | None = Field( 464 default=None, description="Width of the image in pixels. `null` if not known." 465 ) 466 467 468class ThreadMessagesResponseDataMessagesItemAttachmentsItemVariantsItem(BaseModel): 469 content_type: str | None = Field( 470 default=None, 471 description='MIME type of this variant\'s file (e.g., `"image/jpeg"`, `"video/mp4"`). `null` if the file is not loaded.', 472 ) 473 created_at: datetime | None = Field( 474 default=None, description="When this variant was created (ISO 8601)." 475 ) 476 file: str | None = Field( 477 default=None, 478 description="ID of the underlying storage file that backs this variant (`fil_...`).", 479 ) 480 filename: str | None = Field( 481 default=None, 482 description="Original filename of the uploaded file for this variant. `null` if the file is not loaded.", 483 ) 484 height: int | None = Field( 485 default=None, description="Height of this variant in pixels. `null` if not recorded." 486 ) 487 id: str = Field(..., description="Media variant ID (`mvr_...`).") 488 image_source: ( 489 ThreadMessagesResponseDataMessagesItemAttachmentsItemVariantsItemImageSource | None 490 ) = Field( 491 default=None, 492 description="Resolved image delivery metadata for this variant, including dimensions and CDN URL. `null` for non-image content types.", 493 ) 494 updated_at: datetime | None = Field( 495 default=None, description="When this variant was last updated (ISO 8601)." 496 ) 497 url: str | None = Field( 498 default=None, 499 description="Signed download URL for this variant, resolved at request time. `null` if the file is unavailable.", 500 ) 501 variant_key: str | None = Field( 502 default=None, 503 description='Identifier for this variant\'s processing tier. Common values include `"original"` (the unmodified upload) and `"thumbnail"` (a resized preview).', 504 ) 505 width: int | None = Field( 506 default=None, description="Width of this variant in pixels. `null` if not recorded." 507 ) 508 509 510class ThreadMessagesResponseDataMessagesItemAttachmentsItem(BaseModel): 511 content_type: str | None = Field( 512 default=None, 513 description='MIME type of the attached file, e.g. `"image/png"` or `"application/pdf"`. Present on `file`, `artifact`, and `media` types. `null` otherwise.', 514 ) 515 description: str | None = Field( 516 default=None, 517 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.", 518 ) 519 filename: str | None = Field( 520 default=None, 521 description='Original filename of the attached file, e.g. `"report.pdf"`. Present on `file`, `artifact`, and `media` types. `null` otherwise.', 522 ) 523 height: int | None = Field( 524 default=None, 525 description="Height in pixels of the media item. Present on `media` type only. `null` otherwise.", 526 ) 527 id: str = Field(..., description="Unique identifier for this attachment within the message.") 528 image_height: int | None = Field( 529 default=None, 530 description="Height in pixels of the scraped preview image. Present on `scraped_link` type only. `null` otherwise.", 531 ) 532 image_source: ThreadMessagesResponseDataMessagesItemAttachmentsItemImageSource | None = Field( 533 default=None, 534 description="Image source metadata for inline rendering. Present on `file`, `scraped_link`, `artifact`, and `media` types when the content is an image. `null` otherwise.", 535 ) 536 image_url: str | None = Field( 537 default=None, 538 description="URL of the preview image extracted from the scraped page. Present on `scraped_link` type only. `null` otherwise.", 539 ) 540 image_width: int | None = Field( 541 default=None, 542 description="Width in pixels of the scraped preview image. Present on `scraped_link` type only. `null` otherwise.", 543 ) 544 media_type: str | None = Field( 545 default=None, 546 description='The media category, e.g. `"video"` or `"audio"`. Present on `media` type only; omitted otherwise.', 547 ) 548 name: str | None = Field( 549 default=None, 550 description="Display name of the media item. Present on `media` type only. `null` otherwise.", 551 ) 552 object: dict[str, Any] | None = Field( 553 default=None, 554 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.", 555 ) 556 title: str | None = Field( 557 default=None, 558 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.", 559 ) 560 type: str = Field( 561 ..., 562 description='The attachment type. One of `"file"`, `"scraped_link"`, `"artifact"`, `"task"`, `"media"`, `"action"`, or `"chart"`. Determines which additional fields are present.', 563 ) 564 url: str | None = Field( 565 default=None, 566 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.", 567 ) 568 variants: list[ThreadMessagesResponseDataMessagesItemAttachmentsItemVariantsItem] | None = ( 569 Field( 570 default=None, 571 description="Array of available encoding variants for the media item (e.g. different resolutions). Present on `media` type only; omitted otherwise.", 572 ) 573 ) 574 version: int | None = Field( 575 default=None, 576 description="Version number of the attached artifact at the time of attachment. Present on `artifact` type only. `null` otherwise.", 577 ) 578 width: int | None = Field( 579 default=None, 580 description="Width in pixels of the media item. Present on `media` type only. `null` otherwise.", 581 ) 582 583 584class ThreadMessagesResponseDataMessagesItemReactionsItem(BaseModel): 585 payload: dict[str, Any] | None = Field( 586 default=None, 587 description='Type-specific reaction data. For `"emoji_reaction"` reactions, contains an `emoji` key with the Unicode emoji string (e.g., `" "`).', 588 ) 589 type: str = Field( 590 ..., 591 description='Reaction type identifier. Currently always `"emoji_reaction"` for emoji-based reactions.', 592 ) 593 user: str | None = Field( 594 default=None, description="Public ID of the user who added the reaction (`usr_...`)." 595 ) 596 597 598class ThreadMessagesResponseDataMessagesItem(BaseModel): 599 acl: ThreadMessagesResponseDataMessagesItemAcl | None = Field( 600 default=None, 601 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.", 602 ) 603 actors: list[ThreadMessagesResponseDataMessagesItemActorsItem] | None = Field( 604 default=None, 605 description="Resolved actor descriptors for the message sender, combining identity and display metadata. Always contains exactly one entry.", 606 ) 607 agent: str | None = Field( 608 default=None, 609 description="ID of the agent user that sent this message (`agi_...`). `null` for messages sent by human users.", 610 ) 611 agent_mode: Literal["cli", "embedded"] | None = Field( 612 default=None, 613 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.", 614 ) 615 attachments: list[ThreadMessagesResponseDataMessagesItemAttachmentsItem] | None = Field( 616 default=None, 617 description="Files, links, tasks, media, artifacts, and actions attached to this message. Empty array if there are no attachments.", 618 ) 619 branched_thread: str | None = Field( 620 default=None, 621 description="ID of the thread that was branched from this message (`thr_...`). `null` if this message has not spawned a branch thread.", 622 ) 623 content: str | None = Field( 624 default=None, 625 description="Text content of the message. `null` for messages that contain only attachments.", 626 ) 627 created_at: str | None = Field( 628 default=None, description="When the message was posted (ISO 8601)." 629 ) 630 has_replies: bool | None = Field( 631 default=None, 632 description="Whether this message has at least one reply. Only present when explicitly requested or computed by the server.", 633 ) 634 id: str = Field(..., description="Message ID (`msg_...`).") 635 idempotency_key: str | None = Field( 636 default=None, 637 description="Client-supplied idempotency key used to deduplicate message sends. `null` if the sender did not provide one.", 638 ) 639 is_deleted: bool | None = Field( 640 default=None, 641 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.", 642 ) 643 legacy_agent: str | None = Field( 644 default=None, 645 description="Identifier of the legacy chat agent that sent this message, if applicable. `null` for messages sent by users or modern agent users.", 646 ) 647 metadata: dict[str, Any] | None = Field( 648 default=None, 649 description="Arbitrary key-value metadata attached to the message. Always present; defaults to an empty object when no metadata has been set.", 650 ) 651 org: str | None = Field( 652 default=None, description="ID of the organization that owns this message (`org_...`)." 653 ) 654 reactions: list[ThreadMessagesResponseDataMessagesItemReactionsItem] | None = Field( 655 default=None, 656 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.", 657 ) 658 rendering_mode: str | None = Field( 659 default=None, 660 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.', 661 ) 662 replies: list[dict[str, Any]] | None = Field( 663 default=None, 664 description="Inline array of reply messages, each serialized as a full message object. Only present when the server has preloaded replies for this message.", 665 ) 666 replies_after_cursor: str | None = Field( 667 default=None, 668 description="Opaque pagination cursor to fetch replies posted after the current page. Only present when inline replies are included in the response.", 669 ) 670 replies_before_cursor: str | None = Field( 671 default=None, 672 description="Opaque pagination cursor to fetch replies posted before the current page. Only present when inline replies are included in the response.", 673 ) 674 reply_count: int | None = Field( 675 default=None, 676 description="Total number of direct replies to this message. Only present when explicitly requested or computed by the server.", 677 ) 678 reply_to: dict[str, Any] | None = Field( 679 default=None, 680 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.", 681 ) 682 root_message_id: str | None = Field( 683 default=None, 684 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.", 685 ) 686 sandbox: str | None = Field( 687 default=None, 688 description="ID of the developer sandbox this message belongs to (`dsb_...`). `null` for non-sandbox messages.", 689 ) 690 team: str | None = Field( 691 default=None, 692 description="ID of the team this message is scoped to (`tem_...`). `null` if the message is not team-scoped.", 693 ) 694 thread: str | None = Field( 695 default=None, description="ID of the thread this message belongs to (`thr_...`)." 696 ) 697 type: str | None = Field( 698 default=None, 699 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.", 700 ) 701 user: str | dict[str, Any] | None = Field( 702 default=None, 703 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.", 704 ) 705 visibility: Literal["default", "private"] | None = Field( 706 default=None, 707 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.", 708 ) 709 710 711class ThreadMessagesResponseData(BaseModel): 712 after_cursor: str | None = Field( 713 default=None, 714 description="Opaque cursor to pass as `after` to retrieve the page of messages newer than this result set. `null` when there are no later messages.", 715 ) 716 anchor: str | None = Field( 717 default=None, 718 description="Message ID used as the anchor for a windowed query. `null` for ordinary cursor pagination.", 719 ) 720 before_cursor: str | None = Field( 721 default=None, 722 description="Opaque cursor to pass as `before` to retrieve the page of messages older than this result set. `null` when there are no earlier messages.", 723 ) 724 messages: list[ThreadMessagesResponseDataMessagesItem] = Field( 725 ..., description="Ordered array of message objects for this page of results." 726 ) 727 728 729class ThreadMessagesResponse(BaseModel): 730 """ 731 Successful response 732 """ 733 734 data: ThreadMessagesResponseData = Field( 735 ..., 736 description="Pagination envelope containing the messages for this page along with cursors for adjacent pages.", 737 ) 738 739 740class ThreadSearchResponseDataItem(BaseModel): 741 agent: str | None = Field( 742 default=None, 743 description="Agent sender ID (`agi_...`), or `null` when a human sent the message.", 744 ) 745 content: str = Field( 746 ..., 747 description="A bounded snippet around the first matching occurrence (at most 240 characters).", 748 ) 749 created_at: datetime = Field(..., description="When the message was posted.") 750 id: str = Field(..., description="Message ID (`msg_...`).") 751 similarity_score: float | None = Field( 752 default=None, 753 description="Cosine similarity to the query when the result participated in embedding search, or `null` in text mode and for text-only hybrid matches.", 754 ) 755 user: str | None = Field( 756 default=None, 757 description="Human sender ID (`usr_...`), or `null` when an agent sent the message.", 758 ) 759 760 761class ThreadSearchResponse(BaseModel): 762 """ 763 Successful response 764 """ 765 766 after_cursor: str | None = Field( 767 default=None, 768 description="Text-mode cursor for the next page of newer matches, or `null` for ranked modes and empty pages.", 769 ) 770 before_cursor: str | None = Field( 771 default=None, 772 description="Text-mode cursor for the next page of older matches, or `null` for ranked modes and empty pages.", 773 ) 774 data: list[ThreadSearchResponseDataItem] = Field( 775 ..., 776 description="Matching messages ordered newest first in text mode and by relevance in embedding or hybrid mode.", 777 ) 778 has_more: bool = Field( 779 ..., description="`true` when at least one additional visible match exists." 780 ) 781 782 783class ThreadTrajectoriesResponseDataItem(BaseModel): 784 agent_message: str | None = Field( 785 default=None, 786 description="ID of the agent-authored reply message (`msg_...`). `null` if the trajectory has not yet produced a response message.", 787 ) 788 created_at: str | None = Field( 789 default=None, description="When this trajectory link was created (ISO 8601)." 790 ) 791 id: str = Field(..., description="Thread message trajectory ID (`tmt_...`).") 792 org: str | None = Field( 793 default=None, description="ID of the organization this trajectory belongs to (`org_...`)." 794 ) 795 sandbox: str | None = Field( 796 default=None, 797 description="ID of the sandbox environment in which this trajectory was produced (`dsb_...`). `null` in production contexts.", 798 ) 799 thread: str | None = Field( 800 default=None, description="ID of the thread containing the linked messages (`thr_...`)." 801 ) 802 trajectory: str | None = Field( 803 default=None, 804 description="ID of the AI trajectory record that captures the full model interaction for this exchange (`trj_...`).", 805 ) 806 updated_at: str | None = Field( 807 default=None, description="When this trajectory link was last modified (ISO 8601)." 808 ) 809 user_message: str | None = Field( 810 default=None, 811 description="ID of the user-authored message that triggered the agent response (`msg_...`). `null` if the agent turn was not preceded by a user message.", 812 ) 813 814 815class ThreadTrajectoriesResponse(BaseModel): 816 """ 817 Successful response 818 """ 819 820 after_cursor: str | None = Field( 821 default=None, 822 description="Opaque cursor to pass as `after_cursor` to retrieve the next page. `null` when no further pages exist.", 823 ) 824 before_cursor: str | None = Field( 825 default=None, 826 description="Opaque cursor to pass as `before_cursor` to retrieve the previous page. `null` when this is the first page.", 827 ) 828 data: list[ThreadTrajectoriesResponseDataItem] = Field( 829 ..., 830 description="Array of thread message trajectory objects for the current page. Empty when no trajectories match the query.", 831 ) 832 833 834class AsyncThreadMemberResource: 835 def __init__(self, http: HttpClient): 836 self._http = http 837 838 async def remove(self, thread: str) -> None: 839 """ 840 Remove a member from a thread 841 Removes a user or agent from the explicit roster of a private or restricted 842 thread. Team-visible threads use implicit membership and reject individual 843 removals. A member may remove themself; removing someone else requires 844 permission to modify the thread. A successful removal returns HTTP 204 with 845 no response body. 846 Supply either `user` or `agent` depending on the value of `type`. Returns 404 847 if the thread or the membership record does not exist. 848 849 Args: 850 thread: Thread ID (`thr_...`) identifying the thread to remove the member from. 851 852 Returns: 853 Empty response body. HTTP 204 on success. 854 """ 855 await self._http.request(f"/api/v1/threads/{thread}/members", method="DELETE") 856 857 async def list(self, thread: str) -> ThreadMemberListResponse: 858 """ 859 List members of a thread 860 Returns all current user and agent members. Private and restricted threads 861 return their explicit roster; team-visible threads return the owning team's 862 implicit roster. The authenticated viewer must be able to see the thread. 863 Results are returned as a flat array in the `data` field. The list is not 864 paginated all members are returned in a single response. 865 866 Args: 867 thread: Thread ID (`thr_...`) identifying the thread to remove the member from. 868 869 Returns: 870 Successful response 871 """ 872 return await self._http.request( 873 f"/api/v1/threads/{thread}/members", 874 response_type=ThreadMemberListResponse, 875 ) 876 877 async def create(self, thread: str, input: ThreadMemberCreateInput) -> ChatMember: 878 """ 879 Add a member to a thread 880 Adds a user or agent to the explicit roster of a private or restricted 881 thread. Team-visible threads use the owning team's implicit roster and reject 882 explicit additions. On restricted threads, a team member may add themself; 883 adding anyone else requires permission to modify the thread. 884 Supply either `user` or `agent` depending on the value of `type`. Targets 885 must be visible to the caller and, for an ordinary team-owned thread, must 886 belong to the owning team. On success the membership record is returned with 887 HTTP 201; repeated agent additions are idempotent. 888 889 Args: 890 thread: Thread ID (`thr_...`) identifying the thread to remove the member from. 891 input: Request body. 892 input.agent: Agent ID of the principal to add. Required when `type` is `"agent"`. 893 input.membership_type: Role granted to the new member. One of `"owner"` or `"member"`. Defaults to `"member"`. 894 input.type: Kind of principal being added. Must be `"user"` or `"agent"`. 895 input.user: User ID of the principal to add. Required when `type` is `"user"`. 896 897 Returns: 898 The user or agent membership that was added to the thread. 899 """ 900 return await self._http.request( 901 f"/api/v1/threads/{thread}/members", 902 method="POST", 903 body=input, 904 response_type=ChatMember, 905 ) 906 907 908class AsyncSettingResource: 909 def __init__(self, http: HttpClient): 910 self._http = http 911 912 async def list(self, thread: str) -> SettingListResponse: 913 """ 914 Retrieve thread settings 915 Returns the current settings for the specified thread. Settings control 916 per-thread behavior such as whether the AI agent is enabled. 917 The authenticated user must own the thread or be a member of its workspace. 918 If settings have never been explicitly configured, defaults are returned 919 (for example, `agent_enabled` defaults to `true`). 920 921 Args: 922 thread: Thread ID (`thr_...`). Must belong to the authenticated user's workspace. 923 924 Returns: 925 Successful response 926 """ 927 return await self._http.request( 928 f"/api/v1/threads/{thread}/settings", 929 response_type=SettingListResponse, 930 ) 931 932 async def replace(self, thread: str, input: SettingReplaceInput) -> ThreadSettings: 933 """ 934 Update thread settings 935 Updates the settings for the specified thread. Only fields included in 936 the `settings` map are modified; omitted fields retain their current values. 937 The authenticated user must own the thread or be a member of its workspace. 938 Returns the full settings object reflecting the state after the update. 939 Validation errors are returned as `422 Unprocessable Entity`. 940 941 Args: 942 thread: Thread ID (`thr_...`). Must belong to the authenticated user's workspace. 943 input: Request body. 944 input.settings: Map of settings fields to update. Include only the keys you want to change. 945 946 Returns: 947 The thread settings object after the update has been applied. 948 """ 949 return await self._http.request( 950 f"/api/v1/threads/{thread}/settings", 951 method="PUT", 952 body=input, 953 response_type=ThreadSettings, 954 ) 955 956 957class AsyncTagResource: 958 def __init__(self, http: HttpClient): 959 self._http = http 960 961 async def remove(self, thread: str) -> Thread: 962 """ 963 Remove tags from a thread 964 Removes one or more status tags from the thread and returns the updated 965 thread. Removing a tag the thread does not have is a no-op. 966 Any participant of the thread a human member or an agent member may edit 967 tags. Supply the tags to remove as repeated query parameters, e.g. 968 `?tags[]=blocked&tags[]=needs-review`. 969 970 Args: 971 thread: Thread ID (`thr_...`) to untag. 972 973 Returns: 974 The thread object after the tags were removed. 975 """ 976 return await self._http.request( 977 f"/api/v1/threads/{thread}/tags", 978 method="DELETE", 979 response_type=Thread, 980 ) 981 982 async def create(self, thread: str, input: TagCreateInput) -> Thread: 983 """ 984 Add tags to a thread 985 Adds one or more status tags to the thread and returns the updated thread. 986 Any participant of the thread a human member or an agent member may edit 987 tags; this is broader than the owner/admin permission required to update other 988 thread fields. Adding a tag the thread already has is a no-op. Tags are 989 normalized (trimmed and lowercased) and may contain only lowercase letters, 990 numbers, hyphens, and underscores. 991 992 Args: 993 thread: Thread ID (`thr_...`) to untag. 994 input: Request body. 995 input.tags: Tags to add to the thread. 996 997 Returns: 998 The thread object after the tags were added. 999 """ 1000 return await self._http.request( 1001 f"/api/v1/threads/{thread}/tags", 1002 method="POST", 1003 body=input, 1004 response_type=Thread, 1005 ) 1006 1007 async def replace(self, thread: str, input: TagReplaceInput) -> Thread: 1008 """ 1009 Replace a thread's tags 1010 Replaces the thread's entire set of status tags with the provided list and 1011 returns the updated thread. Passing an empty array clears all tags. 1012 Any participant of the thread a human member or an agent member may edit 1013 tags. Tags are normalized (trimmed and lowercased) and may contain only 1014 lowercase letters, numbers, hyphens, and underscores. 1015 1016 Args: 1017 thread: Thread ID (`thr_...`) to untag. 1018 input: Request body. 1019 input.tags: The complete set of tags for the thread. An empty array clears all tags. 1020 1021 Returns: 1022 The thread object after its tags were replaced. 1023 """ 1024 return await self._http.request( 1025 f"/api/v1/threads/{thread}/tags", 1026 method="PUT", 1027 body=input, 1028 response_type=Thread, 1029 ) 1030 1031 1032class AsyncThreadResource: 1033 def __init__(self, http: HttpClient): 1034 self._http = http 1035 self.members = AsyncThreadMemberResource(http) 1036 self.settings = AsyncSettingResource(http) 1037 self.tags = AsyncTagResource(http) 1038 1039 async def delete(self, thread: str) -> None: 1040 """ 1041 Delete a thread 1042 Permanently deletes a thread and all of its messages and artifacts. This action 1043 cannot be undone. 1044 The authenticated user must own the thread or be an owner of the team the thread 1045 belongs to. Attempting to delete a thread owned by another user or team returns 403. 1046 1047 Args: 1048 thread: Thread ID (`thr_...`). The authenticated user must own this thread. 1049 1050 Returns: 1051 Empty response on successful deletion. 1052 """ 1053 await self._http.request(f"/api/v1/threads/{thread}", method="DELETE") 1054 1055 async def get(self, thread: str) -> Thread: 1056 """ 1057 Retrieve a thread 1058 Returns the full thread record for the given thread ID. The authenticated user 1059 must own the thread or be a member of the workspace it belongs to. 1060 Use this endpoint to fetch the current state of a single thread, including its 1061 title, description, and metadata. To list many threads, use the list endpoint 1062 with cursor-based pagination. 1063 1064 Args: 1065 thread: Thread ID (`thr_...`). The authenticated user must have access to this thread. 1066 1067 Returns: 1068 The requested thread object. 1069 """ 1070 return await self._http.request(f"/api/v1/threads/{thread}", response_type=Thread) 1071 1072 async def replace(self, thread: str, input: ThreadReplaceInput) -> Thread: 1073 """ 1074 Update a thread 1075 Updates one or more mutable properties of the specified thread and returns 1076 the full thread object with the applied changes. Only the fields you provide 1077 are modified; omitted fields retain their current values. 1078 If `profile_picture` is supplied, the image is uploaded before the other 1079 fields are saved, after all ordinary thread fields have passed validation. 1080 Supplying invalid base64 picture data returns 422 and no other fields are 1081 updated. 1082 Visibility can only widen: `private` may become `restricted` or `team`, and 1083 `restricted` may become `team`. The authenticated viewer must have 1084 permission to modify the thread. 1085 Mirror-thread titles, descriptions, and notification state remain editable 1086 by privileged app viewers. Mirror metadata, visibility, and membership are 1087 provider-managed and cannot be changed through this endpoint. 1088 1089 Args: 1090 thread: Thread ID (`thr_...`). The authenticated user must have permission to update this thread. 1091 input: Request body. 1092 input.description: Optional longer text describing the thread's purpose. Replaces the existing description when provided. 1093 input.metadata: Arbitrary key-value metadata to store on the thread. Merged with or replaces existing metadata. 1094 input.muted: When `true`, suppresses notifications for new messages in this thread for the authenticated user. 1095 input.profile_picture: New profile picture for the thread. Provide all three inner fields to replace the existing image. 1096 input.title: Human-readable display name for the thread. Replaces the existing title when provided. 1097 input.visibility: Widen a team-owned thread: `private` may become `restricted` or `team`, and `restricted` may become `team`. Visibility cannot be narrowed. 1098 1099 Returns: 1100 The thread object after the update has been applied. 1101 """ 1102 return await self._http.request( 1103 f"/api/v1/threads/{thread}", 1104 method="PUT", 1105 body=input, 1106 response_type=Thread, 1107 ) 1108 1109 async def agents(self, thread: str) -> ThreadAgentsResponse: 1110 """ 1111 List agents in a thread 1112 Returns the agents participating in the specified thread. Only personal user 1113 threads (threads owned by a single user, not a team) expose agents through 1114 this endpoint; requests for team threads return 404. 1115 The authenticated user must have visibility into the thread. Each agent entry 1116 includes display information such as name and profile picture. Thread-level 1117 overrides (e.g. a custom name or profile picture set for this thread) take 1118 precedence over the agent's default values. When the caller is the thread 1119 owner, each entry also includes an `agent_config` object describing the 1120 agent's message policy and context configuration. 1121 1122 Args: 1123 thread: Thread ID (`thr_...`). Must be a personal user thread visible to the authenticated user. 1124 1125 Returns: 1126 Successful response 1127 """ 1128 return await self._http.request( 1129 f"/api/v1/threads/{thread}/agents", 1130 response_type=ThreadAgentsResponse, 1131 ) 1132 1133 async def artifacts(self, thread: str) -> ThreadArtifactsResponse: 1134 """ 1135 List artifacts for a thread 1136 Returns all artifacts produced during a thread's AI conversation. Artifacts are 1137 structured outputs such as code files, documents, or generated assets created 1138 by the AI agent in response to messages in the thread. 1139 The authenticated user must have access to the specified thread. Results are 1140 returned in a single page; there is no cursor-based pagination for this endpoint. 1141 1142 Args: 1143 thread: Thread ID (`thr_...`). Must be accessible to the authenticated user. 1144 1145 Returns: 1146 Successful response 1147 """ 1148 return await self._http.request( 1149 f"/api/v1/threads/{thread}/artifacts", 1150 response_type=ThreadArtifactsResponse, 1151 ) 1152 1153 async def mark_read(self, thread: str, input: ThreadMarkReadInput) -> None: 1154 """ 1155 Mark a thread as read 1156 Records that a user has read up to a specific message in the thread. Unread 1157 indicators and badge counts are cleared up to the specified message. 1158 You must supply exactly one of `last_read_message` or `use_latest_message`. 1159 Omitting both returns 400. If `use_latest_message` is `true` and the thread 1160 has no messages, the request succeeds silently with no state change. 1161 For server-to-server (S2S) requests where no user identity is present in the 1162 token, the `user` param is required to identify whose read state to update. 1163 1164 Args: 1165 thread: Thread ID (`thr_...`). The thread to mark as read. 1166 input: Request body. 1167 input.last_read_message: Message ID (`msg_...`) to record as the last read message. Mutually exclusive with `use_latest_message`. 1168 input.use_latest_message: When `true`, marks the thread as read up to the latest message. Mutually exclusive with `last_read_message`. 1169 input.user: User ID (`usr_...`) whose read state to update. Required for S2S requests; ignored when an authenticated user is present in the token. 1170 1171 Returns: 1172 Empty response on success. 1173 """ 1174 await self._http.request(f"/api/v1/threads/{thread}/mark_read", method="POST", body=input) 1175 1176 async def messages( 1177 self, 1178 thread: str, 1179 *, 1180 before_cursor: str | None = None, 1181 after_cursor: str | None = None, 1182 metadata: dict[str, Any] | None = None, 1183 limit: int | None = None, 1184 anchor: str | None = None, 1185 direction: Literal["before", "after", "around"] | None = None, 1186 before_limit: int | None = None, 1187 after_limit: int | None = None, 1188 include_anchor: bool | None = None, 1189 anchor_agent_mode: Literal["cli", "embedded"] | None = None, 1190 anchor_agent: str | None = None, 1191 include_reply_counts: bool | None = None, 1192 ) -> ThreadMessagesResponse: 1193 """ 1194 List messages in a thread 1195 Returns a cursor-paginated list of messages belonging to the specified thread, 1196 ordered from oldest to newest. Supply `before_cursor`, `after_cursor`, or both 1197 to page through or bound the result set; omit both to receive the most recent page. 1198 Supply `anchor` and `direction` to fetch a window before, after, or around a 1199 specific message. Use `anchor=last_matching&anchor_agent_mode=embedded` to 1200 resolve the anchor from the latest embedded-agent message, and add 1201 `anchor_agent` to scope that resolution to a single sender agent. 1202 Supply `metadata` as a JSON-encoded structured expression to filter message 1203 metadata before cursor pagination or anchored window limits are applied. 1204 The authenticated user must have access to the thread's owner (workspace or user). 1205 A 403 is returned if the thread exists but is not accessible to the caller; a 404 1206 is returned if the thread does not exist or is not visible to the authenticated user. 1207 Pass `include_reply_counts: true` to annotate each message with the number of 1208 threaded replies it has received. This adds a small amount of latency and should 1209 be omitted when reply counts are not needed. 1210 1211 Args: 1212 thread: Thread ID (`thr_...`). The authenticated user must have access to this thread. 1213 before_cursor: Opaque cursor returned in a previous response's `before_cursor` field. When provided, returns messages immediately before that position. May be combined with `after_cursor` to bound a range. 1214 after_cursor: Opaque cursor returned in a previous response's `after_cursor` field. When provided, returns messages immediately after that position. May be combined with `before_cursor` to bound a range. 1215 metadata: Structured metadata filter expression. Only messages whose `metadata` object satisfies the expression are returned. The filter is applied before cursor pagination and anchored window limits. 1216 limit: Maximum number of messages to return per page. Defaults to 20; maximum is 100. 1217 anchor: Message ID (`msg_...`) to use as a window anchor, or `last_matching` to resolve the anchor from the latest message matching the anchor filters. Cannot be combined with `before_cursor` or `after_cursor`. 1218 direction: Window direction relative to `anchor`. `before` returns older messages, `after` returns newer messages, and `around` returns messages on both sides. Defaults to `after` when `anchor` is supplied. `direction=around` cannot be combined with an explicit `limit`; use `before_limit` and `after_limit`. 1219 before_limit: For `direction=around`, maximum number of messages older than the anchor. Defaults to 20; maximum is 100. 1220 after_limit: For `direction=around`, maximum number of messages newer than the anchor. Defaults to 20; maximum is 100. 1221 include_anchor: Whether to include the anchor message in a window response. Defaults to `true` for `direction=around`; ignored for ordinary cursor pagination and one-sided windows. 1222 anchor_agent_mode: When `anchor=last_matching`, resolve the anchor from the latest message with this local agent execution mode. 1223 anchor_agent: When `anchor=last_matching`, scope the anchor resolution to messages sent by this agent (`agi_...`). Combine with `anchor_agent_mode` to resolve the latest message from a specific agent in a given mode. 1224 include_reply_counts: When `true`, each message in the response is annotated with its threaded reply count. Defaults to `false`. Adds latency; omit when reply counts are not needed. 1225 1226 Returns: 1227 Successful response 1228 """ 1229 query: dict[str, object] = {} 1230 if before_cursor is not None: 1231 query["before_cursor"] = before_cursor 1232 if after_cursor is not None: 1233 query["after_cursor"] = after_cursor 1234 if metadata is not None: 1235 query["metadata"] = metadata 1236 if limit is not None: 1237 query["limit"] = limit 1238 if anchor is not None: 1239 query["anchor"] = anchor 1240 if direction is not None: 1241 query["direction"] = direction 1242 if before_limit is not None: 1243 query["before_limit"] = before_limit 1244 if after_limit is not None: 1245 query["after_limit"] = after_limit 1246 if include_anchor is not None: 1247 query["include_anchor"] = include_anchor 1248 if anchor_agent_mode is not None: 1249 query["anchor_agent_mode"] = anchor_agent_mode 1250 if anchor_agent is not None: 1251 query["anchor_agent"] = anchor_agent 1252 if include_reply_counts is not None: 1253 query["include_reply_counts"] = include_reply_counts 1254 return await self._http.request( 1255 f"/api/v1/threads/{thread}/messages", 1256 query=query, 1257 response_type=ThreadMessagesResponse, 1258 ) 1259 1260 async def picture(self, thread: str, input: ThreadPictureInput) -> Thread: 1261 """ 1262 Update a thread's profile picture 1263 Uploads a new profile picture for the specified thread and returns the updated 1264 thread object. The image must be supplied as a base64-encoded string with its 1265 MIME type. 1266 The authenticated user must own the thread or be a team owner of the workspace 1267 the thread belongs to. Supplying invalid base64 data returns 422. 1268 1269 Args: 1270 thread: Thread ID (`thr_...`). The authenticated user must have permission to update this thread. 1271 input: Request body. 1272 input.picture: Profile picture payload. Must include the base64-encoded image data and its MIME type. 1273 1274 Returns: 1275 The thread object after the profile picture has been updated. 1276 """ 1277 return await self._http.request( 1278 f"/api/v1/threads/{thread}/picture", 1279 method="PUT", 1280 body=input, 1281 response_type=Thread, 1282 ) 1283 1284 async def read_status(self, thread: str, *, user: str | None = None) -> ThreadReadStatus: 1285 """ 1286 Retrieve a thread's read status 1287 Returns the read status of a thread for the specified user, including the ID 1288 of the last message they have read and the number of unread messages remaining. 1289 For user-authenticated requests, the status is always returned for the 1290 authenticated user and the `user` parameter is ignored. For server-to-server 1291 (S2S) requests, the `user` parameter is required and must be a valid user ID. 1292 Returns 404 if the thread does not exist or the caller does not have access 1293 to it. 1294 1295 Args: 1296 thread: Thread ID (`thr_...`). Must be accessible to the authenticated user or, for S2S requests, to the specified user. 1297 user: User ID (`usr_...`) whose read status to retrieve. Required for S2S requests; ignored for user-authenticated requests, which always return the status for the authenticated user. 1298 1299 Returns: 1300 The read status record for the requested thread and user. 1301 """ 1302 query: dict[str, object] = {} 1303 if user is not None: 1304 query["user"] = user 1305 return await self._http.request( 1306 f"/api/v1/threads/{thread}/read_status", 1307 query=query, 1308 response_type=ThreadReadStatus, 1309 ) 1310 1311 async def search( 1312 self, 1313 thread: str, 1314 q: str, 1315 *, 1316 app: str | None = None, 1317 limit: int | None = None, 1318 mode: Literal["text", "embedding", "hybrid"] | None = None, 1319 before_cursor: str | None = None, 1320 after_cursor: str | None = None, 1321 ) -> ThreadSearchResponse: 1322 """ 1323 Search messages in a thread 1324 Searches canonical message content in the specified thread. `"text"` mode 1325 performs the existing case-insensitive substring search, `"embedding"` ranks 1326 stored message embeddings by cosine similarity, and `"hybrid"` combines the 1327 text and embedding rankings with Reciprocal Rank Fusion (RRF). Only messages 1328 visible to the authenticated caller are considered. 1329 Results are intentionally lean: each row contains only a bounded content 1330 snippet, sender identity, and timestamp. Attachments, reactions, ACLs, and 1331 metadata are neither hydrated nor serialized. At most 20 results are 1332 returned. Text results support chronological cursor pagination. Embedding and 1333 hybrid results are relevance-ranked single pages and return null cursors. 1334 1335 Args: 1336 thread: Thread ID (`thr_...`). Must be visible to the authenticated caller. 1337 app: App ID (`app_...`). Required by the protected developer mount and omitted from the public mount. 1338 q: Text or semantic search query. Must contain 3 to 200 characters after trimming. 1339 limit: Maximum number of results. Defaults to 20 and is capped at 20. 1340 mode: Search algorithm: `text` for substring matching, `embedding` for cosine similarity, or `hybrid` for RRF over both rankings. 1341 before_cursor: Text mode only. Opaque cursor returned by a previous page; fetches older matches. 1342 after_cursor: Text mode only. Opaque cursor returned by a previous page; fetches newer matches. 1343 1344 Returns: 1345 Successful response 1346 """ 1347 query: dict[str, object] = {} 1348 if app is not None: 1349 query["app"] = app 1350 query["q"] = q 1351 if limit is not None: 1352 query["limit"] = limit 1353 if mode is not None: 1354 query["mode"] = mode 1355 if before_cursor is not None: 1356 query["before_cursor"] = before_cursor 1357 if after_cursor is not None: 1358 query["after_cursor"] = after_cursor 1359 return await self._http.request( 1360 f"/api/v1/threads/{thread}/search", 1361 query=query, 1362 response_type=ThreadSearchResponse, 1363 ) 1364 1365 async def trajectories( 1366 self, 1367 thread: str, 1368 *, 1369 before_cursor: str | None = None, 1370 after_cursor: str | None = None, 1371 limit: int | None = None, 1372 message: str | None = None, 1373 ) -> ThreadTrajectoriesResponse: 1374 """ 1375 List trajectories for a thread 1376 Returns a cursor-paginated list of thread message trajectories associated with the 1377 specified thread. Each trajectory links a user message and its agent response to the 1378 underlying AI trajectory record that captured the model's reasoning steps. 1379 The authenticated user must own the thread or be a member of the workspace it belongs 1380 to. Results are returned in reverse chronological order by default. Use `before_cursor` 1381 and `after_cursor` to navigate pages; provide at most one cursor per request. 1382 Optionally filter results to trajectories produced in response to a specific message 1383 by supplying the `message` parameter. When no trajectories match the query, `data` 1384 is an empty array and both cursor fields are `null`. A cursor that cannot be decoded 1385 returns a 400 `invalid_cursor` error. 1386 1387 Args: 1388 thread: Thread ID (`thr_...`). The authenticated user must own this thread or belong to its workspace. 1389 before_cursor: Opaque cursor from a previous response's `before_cursor` field. Returns the page of results preceding that cursor position. 1390 after_cursor: Opaque cursor from a previous response's `after_cursor` field. Returns the page of results following that cursor position. 1391 limit: Maximum number of trajectories to return per page. Defaults to 20; maximum is 100. 1392 message: Message ID (`msg_...`). When provided, limits results to trajectories associated with this specific message. 1393 1394 Returns: 1395 Successful response 1396 """ 1397 query: dict[str, object] = {} 1398 if before_cursor is not None: 1399 query["before_cursor"] = before_cursor 1400 if after_cursor is not None: 1401 query["after_cursor"] = after_cursor 1402 if limit is not None: 1403 query["limit"] = limit 1404 if message is not None: 1405 query["message"] = message 1406 return await self._http.request( 1407 f"/api/v1/threads/{thread}/trajectories", 1408 query=query, 1409 response_type=ThreadTrajectoriesResponse, 1410 ) 1411 1412 1413class ThreadMemberResource: 1414 def __init__(self, http: SyncHttpClient): 1415 self._http = http 1416 1417 def remove(self, thread: str) -> None: 1418 """ 1419 Remove a member from a thread 1420 Removes a user or agent from the explicit roster of a private or restricted 1421 thread. Team-visible threads use implicit membership and reject individual 1422 removals. A member may remove themself; removing someone else requires 1423 permission to modify the thread. A successful removal returns HTTP 204 with 1424 no response body. 1425 Supply either `user` or `agent` depending on the value of `type`. Returns 404 1426 if the thread or the membership record does not exist. 1427 1428 Args: 1429 thread: Thread ID (`thr_...`) identifying the thread to remove the member from. 1430 1431 Returns: 1432 Empty response body. HTTP 204 on success. 1433 """ 1434 self._http.request(f"/api/v1/threads/{thread}/members", method="DELETE") 1435 1436 def list(self, thread: str) -> ThreadMemberListResponse: 1437 """ 1438 List members of a thread 1439 Returns all current user and agent members. Private and restricted threads 1440 return their explicit roster; team-visible threads return the owning team's 1441 implicit roster. The authenticated viewer must be able to see the thread. 1442 Results are returned as a flat array in the `data` field. The list is not 1443 paginated all members are returned in a single response. 1444 1445 Args: 1446 thread: Thread ID (`thr_...`) identifying the thread to remove the member from. 1447 1448 Returns: 1449 Successful response 1450 """ 1451 return self._http.request( 1452 f"/api/v1/threads/{thread}/members", 1453 response_type=ThreadMemberListResponse, 1454 ) 1455 1456 def create(self, thread: str, input: ThreadMemberCreateInput) -> ChatMember: 1457 """ 1458 Add a member to a thread 1459 Adds a user or agent to the explicit roster of a private or restricted 1460 thread. Team-visible threads use the owning team's implicit roster and reject 1461 explicit additions. On restricted threads, a team member may add themself; 1462 adding anyone else requires permission to modify the thread. 1463 Supply either `user` or `agent` depending on the value of `type`. Targets 1464 must be visible to the caller and, for an ordinary team-owned thread, must 1465 belong to the owning team. On success the membership record is returned with 1466 HTTP 201; repeated agent additions are idempotent. 1467 1468 Args: 1469 thread: Thread ID (`thr_...`) identifying the thread to remove the member from. 1470 input: Request body. 1471 input.agent: Agent ID of the principal to add. Required when `type` is `"agent"`. 1472 input.membership_type: Role granted to the new member. One of `"owner"` or `"member"`. Defaults to `"member"`. 1473 input.type: Kind of principal being added. Must be `"user"` or `"agent"`. 1474 input.user: User ID of the principal to add. Required when `type` is `"user"`. 1475 1476 Returns: 1477 The user or agent membership that was added to the thread. 1478 """ 1479 return self._http.request( 1480 f"/api/v1/threads/{thread}/members", 1481 method="POST", 1482 body=input, 1483 response_type=ChatMember, 1484 ) 1485 1486 1487class SettingResource: 1488 def __init__(self, http: SyncHttpClient): 1489 self._http = http 1490 1491 def list(self, thread: str) -> SettingListResponse: 1492 """ 1493 Retrieve thread settings 1494 Returns the current settings for the specified thread. Settings control 1495 per-thread behavior such as whether the AI agent is enabled. 1496 The authenticated user must own the thread or be a member of its workspace. 1497 If settings have never been explicitly configured, defaults are returned 1498 (for example, `agent_enabled` defaults to `true`). 1499 1500 Args: 1501 thread: Thread ID (`thr_...`). Must belong to the authenticated user's workspace. 1502 1503 Returns: 1504 Successful response 1505 """ 1506 return self._http.request( 1507 f"/api/v1/threads/{thread}/settings", 1508 response_type=SettingListResponse, 1509 ) 1510 1511 def replace(self, thread: str, input: SettingReplaceInput) -> ThreadSettings: 1512 """ 1513 Update thread settings 1514 Updates the settings for the specified thread. Only fields included in 1515 the `settings` map are modified; omitted fields retain their current values. 1516 The authenticated user must own the thread or be a member of its workspace. 1517 Returns the full settings object reflecting the state after the update. 1518 Validation errors are returned as `422 Unprocessable Entity`. 1519 1520 Args: 1521 thread: Thread ID (`thr_...`). Must belong to the authenticated user's workspace. 1522 input: Request body. 1523 input.settings: Map of settings fields to update. Include only the keys you want to change. 1524 1525 Returns: 1526 The thread settings object after the update has been applied. 1527 """ 1528 return self._http.request( 1529 f"/api/v1/threads/{thread}/settings", 1530 method="PUT", 1531 body=input, 1532 response_type=ThreadSettings, 1533 ) 1534 1535 1536class TagResource: 1537 def __init__(self, http: SyncHttpClient): 1538 self._http = http 1539 1540 def remove(self, thread: str) -> Thread: 1541 """ 1542 Remove tags from a thread 1543 Removes one or more status tags from the thread and returns the updated 1544 thread. Removing a tag the thread does not have is a no-op. 1545 Any participant of the thread a human member or an agent member may edit 1546 tags. Supply the tags to remove as repeated query parameters, e.g. 1547 `?tags[]=blocked&tags[]=needs-review`. 1548 1549 Args: 1550 thread: Thread ID (`thr_...`) to untag. 1551 1552 Returns: 1553 The thread object after the tags were removed. 1554 """ 1555 return self._http.request( 1556 f"/api/v1/threads/{thread}/tags", 1557 method="DELETE", 1558 response_type=Thread, 1559 ) 1560 1561 def create(self, thread: str, input: TagCreateInput) -> Thread: 1562 """ 1563 Add tags to a thread 1564 Adds one or more status tags to the thread and returns the updated thread. 1565 Any participant of the thread a human member or an agent member may edit 1566 tags; this is broader than the owner/admin permission required to update other 1567 thread fields. Adding a tag the thread already has is a no-op. Tags are 1568 normalized (trimmed and lowercased) and may contain only lowercase letters, 1569 numbers, hyphens, and underscores. 1570 1571 Args: 1572 thread: Thread ID (`thr_...`) to untag. 1573 input: Request body. 1574 input.tags: Tags to add to the thread. 1575 1576 Returns: 1577 The thread object after the tags were added. 1578 """ 1579 return self._http.request( 1580 f"/api/v1/threads/{thread}/tags", 1581 method="POST", 1582 body=input, 1583 response_type=Thread, 1584 ) 1585 1586 def replace(self, thread: str, input: TagReplaceInput) -> Thread: 1587 """ 1588 Replace a thread's tags 1589 Replaces the thread's entire set of status tags with the provided list and 1590 returns the updated thread. Passing an empty array clears all tags. 1591 Any participant of the thread a human member or an agent member may edit 1592 tags. Tags are normalized (trimmed and lowercased) and may contain only 1593 lowercase letters, numbers, hyphens, and underscores. 1594 1595 Args: 1596 thread: Thread ID (`thr_...`) to untag. 1597 input: Request body. 1598 input.tags: The complete set of tags for the thread. An empty array clears all tags. 1599 1600 Returns: 1601 The thread object after its tags were replaced. 1602 """ 1603 return self._http.request( 1604 f"/api/v1/threads/{thread}/tags", 1605 method="PUT", 1606 body=input, 1607 response_type=Thread, 1608 ) 1609 1610 1611class ThreadResource: 1612 def __init__(self, http: SyncHttpClient): 1613 self._http = http 1614 self.members = ThreadMemberResource(http) 1615 self.settings = SettingResource(http) 1616 self.tags = TagResource(http) 1617 1618 def delete(self, thread: str) -> None: 1619 """ 1620 Delete a thread 1621 Permanently deletes a thread and all of its messages and artifacts. This action 1622 cannot be undone. 1623 The authenticated user must own the thread or be an owner of the team the thread 1624 belongs to. Attempting to delete a thread owned by another user or team returns 403. 1625 1626 Args: 1627 thread: Thread ID (`thr_...`). The authenticated user must own this thread. 1628 1629 Returns: 1630 Empty response on successful deletion. 1631 """ 1632 self._http.request(f"/api/v1/threads/{thread}", method="DELETE") 1633 1634 def get(self, thread: str) -> Thread: 1635 """ 1636 Retrieve a thread 1637 Returns the full thread record for the given thread ID. The authenticated user 1638 must own the thread or be a member of the workspace it belongs to. 1639 Use this endpoint to fetch the current state of a single thread, including its 1640 title, description, and metadata. To list many threads, use the list endpoint 1641 with cursor-based pagination. 1642 1643 Args: 1644 thread: Thread ID (`thr_...`). The authenticated user must have access to this thread. 1645 1646 Returns: 1647 The requested thread object. 1648 """ 1649 return self._http.request(f"/api/v1/threads/{thread}", response_type=Thread) 1650 1651 def replace(self, thread: str, input: ThreadReplaceInput) -> Thread: 1652 """ 1653 Update a thread 1654 Updates one or more mutable properties of the specified thread and returns 1655 the full thread object with the applied changes. Only the fields you provide 1656 are modified; omitted fields retain their current values. 1657 If `profile_picture` is supplied, the image is uploaded before the other 1658 fields are saved, after all ordinary thread fields have passed validation. 1659 Supplying invalid base64 picture data returns 422 and no other fields are 1660 updated. 1661 Visibility can only widen: `private` may become `restricted` or `team`, and 1662 `restricted` may become `team`. The authenticated viewer must have 1663 permission to modify the thread. 1664 Mirror-thread titles, descriptions, and notification state remain editable 1665 by privileged app viewers. Mirror metadata, visibility, and membership are 1666 provider-managed and cannot be changed through this endpoint. 1667 1668 Args: 1669 thread: Thread ID (`thr_...`). The authenticated user must have permission to update this thread. 1670 input: Request body. 1671 input.description: Optional longer text describing the thread's purpose. Replaces the existing description when provided. 1672 input.metadata: Arbitrary key-value metadata to store on the thread. Merged with or replaces existing metadata. 1673 input.muted: When `true`, suppresses notifications for new messages in this thread for the authenticated user. 1674 input.profile_picture: New profile picture for the thread. Provide all three inner fields to replace the existing image. 1675 input.title: Human-readable display name for the thread. Replaces the existing title when provided. 1676 input.visibility: Widen a team-owned thread: `private` may become `restricted` or `team`, and `restricted` may become `team`. Visibility cannot be narrowed. 1677 1678 Returns: 1679 The thread object after the update has been applied. 1680 """ 1681 return self._http.request( 1682 f"/api/v1/threads/{thread}", 1683 method="PUT", 1684 body=input, 1685 response_type=Thread, 1686 ) 1687 1688 def agents(self, thread: str) -> ThreadAgentsResponse: 1689 """ 1690 List agents in a thread 1691 Returns the agents participating in the specified thread. Only personal user 1692 threads (threads owned by a single user, not a team) expose agents through 1693 this endpoint; requests for team threads return 404. 1694 The authenticated user must have visibility into the thread. Each agent entry 1695 includes display information such as name and profile picture. Thread-level 1696 overrides (e.g. a custom name or profile picture set for this thread) take 1697 precedence over the agent's default values. When the caller is the thread 1698 owner, each entry also includes an `agent_config` object describing the 1699 agent's message policy and context configuration. 1700 1701 Args: 1702 thread: Thread ID (`thr_...`). Must be a personal user thread visible to the authenticated user. 1703 1704 Returns: 1705 Successful response 1706 """ 1707 return self._http.request( 1708 f"/api/v1/threads/{thread}/agents", 1709 response_type=ThreadAgentsResponse, 1710 ) 1711 1712 def artifacts(self, thread: str) -> ThreadArtifactsResponse: 1713 """ 1714 List artifacts for a thread 1715 Returns all artifacts produced during a thread's AI conversation. Artifacts are 1716 structured outputs such as code files, documents, or generated assets created 1717 by the AI agent in response to messages in the thread. 1718 The authenticated user must have access to the specified thread. Results are 1719 returned in a single page; there is no cursor-based pagination for this endpoint. 1720 1721 Args: 1722 thread: Thread ID (`thr_...`). Must be accessible to the authenticated user. 1723 1724 Returns: 1725 Successful response 1726 """ 1727 return self._http.request( 1728 f"/api/v1/threads/{thread}/artifacts", 1729 response_type=ThreadArtifactsResponse, 1730 ) 1731 1732 def mark_read(self, thread: str, input: ThreadMarkReadInput) -> None: 1733 """ 1734 Mark a thread as read 1735 Records that a user has read up to a specific message in the thread. Unread 1736 indicators and badge counts are cleared up to the specified message. 1737 You must supply exactly one of `last_read_message` or `use_latest_message`. 1738 Omitting both returns 400. If `use_latest_message` is `true` and the thread 1739 has no messages, the request succeeds silently with no state change. 1740 For server-to-server (S2S) requests where no user identity is present in the 1741 token, the `user` param is required to identify whose read state to update. 1742 1743 Args: 1744 thread: Thread ID (`thr_...`). The thread to mark as read. 1745 input: Request body. 1746 input.last_read_message: Message ID (`msg_...`) to record as the last read message. Mutually exclusive with `use_latest_message`. 1747 input.use_latest_message: When `true`, marks the thread as read up to the latest message. Mutually exclusive with `last_read_message`. 1748 input.user: User ID (`usr_...`) whose read state to update. Required for S2S requests; ignored when an authenticated user is present in the token. 1749 1750 Returns: 1751 Empty response on success. 1752 """ 1753 self._http.request(f"/api/v1/threads/{thread}/mark_read", method="POST", body=input) 1754 1755 def messages( 1756 self, 1757 thread: str, 1758 *, 1759 before_cursor: str | None = None, 1760 after_cursor: str | None = None, 1761 metadata: dict[str, Any] | None = None, 1762 limit: int | None = None, 1763 anchor: str | None = None, 1764 direction: Literal["before", "after", "around"] | None = None, 1765 before_limit: int | None = None, 1766 after_limit: int | None = None, 1767 include_anchor: bool | None = None, 1768 anchor_agent_mode: Literal["cli", "embedded"] | None = None, 1769 anchor_agent: str | None = None, 1770 include_reply_counts: bool | None = None, 1771 ) -> ThreadMessagesResponse: 1772 """ 1773 List messages in a thread 1774 Returns a cursor-paginated list of messages belonging to the specified thread, 1775 ordered from oldest to newest. Supply `before_cursor`, `after_cursor`, or both 1776 to page through or bound the result set; omit both to receive the most recent page. 1777 Supply `anchor` and `direction` to fetch a window before, after, or around a 1778 specific message. Use `anchor=last_matching&anchor_agent_mode=embedded` to 1779 resolve the anchor from the latest embedded-agent message, and add 1780 `anchor_agent` to scope that resolution to a single sender agent. 1781 Supply `metadata` as a JSON-encoded structured expression to filter message 1782 metadata before cursor pagination or anchored window limits are applied. 1783 The authenticated user must have access to the thread's owner (workspace or user). 1784 A 403 is returned if the thread exists but is not accessible to the caller; a 404 1785 is returned if the thread does not exist or is not visible to the authenticated user. 1786 Pass `include_reply_counts: true` to annotate each message with the number of 1787 threaded replies it has received. This adds a small amount of latency and should 1788 be omitted when reply counts are not needed. 1789 1790 Args: 1791 thread: Thread ID (`thr_...`). The authenticated user must have access to this thread. 1792 before_cursor: Opaque cursor returned in a previous response's `before_cursor` field. When provided, returns messages immediately before that position. May be combined with `after_cursor` to bound a range. 1793 after_cursor: Opaque cursor returned in a previous response's `after_cursor` field. When provided, returns messages immediately after that position. May be combined with `before_cursor` to bound a range. 1794 metadata: Structured metadata filter expression. Only messages whose `metadata` object satisfies the expression are returned. The filter is applied before cursor pagination and anchored window limits. 1795 limit: Maximum number of messages to return per page. Defaults to 20; maximum is 100. 1796 anchor: Message ID (`msg_...`) to use as a window anchor, or `last_matching` to resolve the anchor from the latest message matching the anchor filters. Cannot be combined with `before_cursor` or `after_cursor`. 1797 direction: Window direction relative to `anchor`. `before` returns older messages, `after` returns newer messages, and `around` returns messages on both sides. Defaults to `after` when `anchor` is supplied. `direction=around` cannot be combined with an explicit `limit`; use `before_limit` and `after_limit`. 1798 before_limit: For `direction=around`, maximum number of messages older than the anchor. Defaults to 20; maximum is 100. 1799 after_limit: For `direction=around`, maximum number of messages newer than the anchor. Defaults to 20; maximum is 100. 1800 include_anchor: Whether to include the anchor message in a window response. Defaults to `true` for `direction=around`; ignored for ordinary cursor pagination and one-sided windows. 1801 anchor_agent_mode: When `anchor=last_matching`, resolve the anchor from the latest message with this local agent execution mode. 1802 anchor_agent: When `anchor=last_matching`, scope the anchor resolution to messages sent by this agent (`agi_...`). Combine with `anchor_agent_mode` to resolve the latest message from a specific agent in a given mode. 1803 include_reply_counts: When `true`, each message in the response is annotated with its threaded reply count. Defaults to `false`. Adds latency; omit when reply counts are not needed. 1804 1805 Returns: 1806 Successful response 1807 """ 1808 query: dict[str, object] = {} 1809 if before_cursor is not None: 1810 query["before_cursor"] = before_cursor 1811 if after_cursor is not None: 1812 query["after_cursor"] = after_cursor 1813 if metadata is not None: 1814 query["metadata"] = metadata 1815 if limit is not None: 1816 query["limit"] = limit 1817 if anchor is not None: 1818 query["anchor"] = anchor 1819 if direction is not None: 1820 query["direction"] = direction 1821 if before_limit is not None: 1822 query["before_limit"] = before_limit 1823 if after_limit is not None: 1824 query["after_limit"] = after_limit 1825 if include_anchor is not None: 1826 query["include_anchor"] = include_anchor 1827 if anchor_agent_mode is not None: 1828 query["anchor_agent_mode"] = anchor_agent_mode 1829 if anchor_agent is not None: 1830 query["anchor_agent"] = anchor_agent 1831 if include_reply_counts is not None: 1832 query["include_reply_counts"] = include_reply_counts 1833 return self._http.request( 1834 f"/api/v1/threads/{thread}/messages", 1835 query=query, 1836 response_type=ThreadMessagesResponse, 1837 ) 1838 1839 def picture(self, thread: str, input: ThreadPictureInput) -> Thread: 1840 """ 1841 Update a thread's profile picture 1842 Uploads a new profile picture for the specified thread and returns the updated 1843 thread object. The image must be supplied as a base64-encoded string with its 1844 MIME type. 1845 The authenticated user must own the thread or be a team owner of the workspace 1846 the thread belongs to. Supplying invalid base64 data returns 422. 1847 1848 Args: 1849 thread: Thread ID (`thr_...`). The authenticated user must have permission to update this thread. 1850 input: Request body. 1851 input.picture: Profile picture payload. Must include the base64-encoded image data and its MIME type. 1852 1853 Returns: 1854 The thread object after the profile picture has been updated. 1855 """ 1856 return self._http.request( 1857 f"/api/v1/threads/{thread}/picture", 1858 method="PUT", 1859 body=input, 1860 response_type=Thread, 1861 ) 1862 1863 def read_status(self, thread: str, *, user: str | None = None) -> ThreadReadStatus: 1864 """ 1865 Retrieve a thread's read status 1866 Returns the read status of a thread for the specified user, including the ID 1867 of the last message they have read and the number of unread messages remaining. 1868 For user-authenticated requests, the status is always returned for the 1869 authenticated user and the `user` parameter is ignored. For server-to-server 1870 (S2S) requests, the `user` parameter is required and must be a valid user ID. 1871 Returns 404 if the thread does not exist or the caller does not have access 1872 to it. 1873 1874 Args: 1875 thread: Thread ID (`thr_...`). Must be accessible to the authenticated user or, for S2S requests, to the specified user. 1876 user: User ID (`usr_...`) whose read status to retrieve. Required for S2S requests; ignored for user-authenticated requests, which always return the status for the authenticated user. 1877 1878 Returns: 1879 The read status record for the requested thread and user. 1880 """ 1881 query: dict[str, object] = {} 1882 if user is not None: 1883 query["user"] = user 1884 return self._http.request( 1885 f"/api/v1/threads/{thread}/read_status", 1886 query=query, 1887 response_type=ThreadReadStatus, 1888 ) 1889 1890 def search( 1891 self, 1892 thread: str, 1893 q: str, 1894 *, 1895 app: str | None = None, 1896 limit: int | None = None, 1897 mode: Literal["text", "embedding", "hybrid"] | None = None, 1898 before_cursor: str | None = None, 1899 after_cursor: str | None = None, 1900 ) -> ThreadSearchResponse: 1901 """ 1902 Search messages in a thread 1903 Searches canonical message content in the specified thread. `"text"` mode 1904 performs the existing case-insensitive substring search, `"embedding"` ranks 1905 stored message embeddings by cosine similarity, and `"hybrid"` combines the 1906 text and embedding rankings with Reciprocal Rank Fusion (RRF). Only messages 1907 visible to the authenticated caller are considered. 1908 Results are intentionally lean: each row contains only a bounded content 1909 snippet, sender identity, and timestamp. Attachments, reactions, ACLs, and 1910 metadata are neither hydrated nor serialized. At most 20 results are 1911 returned. Text results support chronological cursor pagination. Embedding and 1912 hybrid results are relevance-ranked single pages and return null cursors. 1913 1914 Args: 1915 thread: Thread ID (`thr_...`). Must be visible to the authenticated caller. 1916 app: App ID (`app_...`). Required by the protected developer mount and omitted from the public mount. 1917 q: Text or semantic search query. Must contain 3 to 200 characters after trimming. 1918 limit: Maximum number of results. Defaults to 20 and is capped at 20. 1919 mode: Search algorithm: `text` for substring matching, `embedding` for cosine similarity, or `hybrid` for RRF over both rankings. 1920 before_cursor: Text mode only. Opaque cursor returned by a previous page; fetches older matches. 1921 after_cursor: Text mode only. Opaque cursor returned by a previous page; fetches newer matches. 1922 1923 Returns: 1924 Successful response 1925 """ 1926 query: dict[str, object] = {} 1927 if app is not None: 1928 query["app"] = app 1929 query["q"] = q 1930 if limit is not None: 1931 query["limit"] = limit 1932 if mode is not None: 1933 query["mode"] = mode 1934 if before_cursor is not None: 1935 query["before_cursor"] = before_cursor 1936 if after_cursor is not None: 1937 query["after_cursor"] = after_cursor 1938 return self._http.request( 1939 f"/api/v1/threads/{thread}/search", 1940 query=query, 1941 response_type=ThreadSearchResponse, 1942 ) 1943 1944 def trajectories( 1945 self, 1946 thread: str, 1947 *, 1948 before_cursor: str | None = None, 1949 after_cursor: str | None = None, 1950 limit: int | None = None, 1951 message: str | None = None, 1952 ) -> ThreadTrajectoriesResponse: 1953 """ 1954 List trajectories for a thread 1955 Returns a cursor-paginated list of thread message trajectories associated with the 1956 specified thread. Each trajectory links a user message and its agent response to the 1957 underlying AI trajectory record that captured the model's reasoning steps. 1958 The authenticated user must own the thread or be a member of the workspace it belongs 1959 to. Results are returned in reverse chronological order by default. Use `before_cursor` 1960 and `after_cursor` to navigate pages; provide at most one cursor per request. 1961 Optionally filter results to trajectories produced in response to a specific message 1962 by supplying the `message` parameter. When no trajectories match the query, `data` 1963 is an empty array and both cursor fields are `null`. A cursor that cannot be decoded 1964 returns a 400 `invalid_cursor` error. 1965 1966 Args: 1967 thread: Thread ID (`thr_...`). The authenticated user must own this thread or belong to its workspace. 1968 before_cursor: Opaque cursor from a previous response's `before_cursor` field. Returns the page of results preceding that cursor position. 1969 after_cursor: Opaque cursor from a previous response's `after_cursor` field. Returns the page of results following that cursor position. 1970 limit: Maximum number of trajectories to return per page. Defaults to 20; maximum is 100. 1971 message: Message ID (`msg_...`). When provided, limits results to trajectories associated with this specific message. 1972 1973 Returns: 1974 Successful response 1975 """ 1976 query: dict[str, object] = {} 1977 if before_cursor is not None: 1978 query["before_cursor"] = before_cursor 1979 if after_cursor is not None: 1980 query["after_cursor"] = after_cursor 1981 if limit is not None: 1982 query["limit"] = limit 1983 if message is not None: 1984 query["message"] = message 1985 return self._http.request( 1986 f"/api/v1/threads/{thread}/trajectories", 1987 query=query, 1988 response_type=ThreadTrajectoriesResponse, 1989 )
18class ThreadMemberCreateInput(TypedDict, total=False): 19 "Add a member to a thread" 20 21 agent: str | None 22 'Agent ID of the principal to add. Required when `type` is `"agent"`.' 23 membership_type: str | None 24 'Role granted to the new member. One of `"owner"` or `"member"`. Defaults to `"member"`.' 25 type: Required[str] 26 'Kind of principal being added. Must be `"user"` or `"agent"`.' 27 user: str | None 28 'User ID of the principal to add. Required when `type` is `"user"`.'
Add a member to a thread
31class SettingReplaceInput(TypedDict): 32 "Update thread settings" 33 34 settings: dict[str, Any] 35 "Map of settings fields to update. Include only the keys you want to change."
Update thread settings
38class TagCreateInput(TypedDict): 39 "Add tags to a thread" 40 41 tags: list[str] 42 "Tags to add to the thread."
Add tags to a thread
45class TagReplaceInput(TypedDict): 46 "Replace a thread's tags" 47 48 tags: list[str] 49 "The complete set of tags for the thread. An empty array clears all tags."
Replace a thread's tags
52class ThreadReplaceInputProfilePicture(TypedDict, total=False): 53 data: str | None 54 "Base64-encoded image payload. Must be a valid base64 string." 55 filename: str | None 56 'Original filename of the image, e.g. `"avatar.png"`. Used for storage metadata.' 57 mime_type: str | None 58 'MIME type of the image, e.g. `"image/jpeg"` or `"image/png"`.'
61class ThreadReplaceInput(TypedDict, total=False): 62 "Update a thread" 63 64 description: str | None 65 "Optional longer text describing the thread's purpose. Replaces the existing description when provided." 66 metadata: dict[str, Any] | None 67 "Arbitrary key-value metadata to store on the thread. Merged with or replaces existing metadata." 68 muted: bool | None 69 "When `true`, suppresses notifications for new messages in this thread for the authenticated user." 70 profile_picture: ThreadReplaceInputProfilePicture | None 71 "New profile picture for the thread. Provide all three inner fields to replace the existing image." 72 title: str | None 73 "Human-readable display name for the thread. Replaces the existing title when provided." 74 visibility: Literal["private", "restricted", "team"] | None 75 "Widen a team-owned thread: `private` may become `restricted` or `team`, and `restricted` may become `team`. Visibility cannot be narrowed."
Update a thread
Optional longer text describing the thread's purpose. Replaces the existing description when provided.
Arbitrary key-value metadata to store on the thread. Merged with or replaces existing metadata.
When true, suppresses notifications for new messages in this thread for the authenticated user.
New profile picture for the thread. Provide all three inner fields to replace the existing image.
78class ThreadMarkReadInput(TypedDict, total=False): 79 "Mark a thread as read" 80 81 last_read_message: str | None 82 "Message ID (`msg_...`) to record as the last read message. Mutually exclusive with `use_latest_message`." 83 use_latest_message: bool | None 84 "When `true`, marks the thread as read up to the latest message. Mutually exclusive with `last_read_message`." 85 user: str | None 86 "User ID (`usr_...`) whose read state to update. Required for S2S requests; ignored when an authenticated user is present in the token."
Mark a thread as read
Message ID (msg_...) to record as the last read message. Mutually exclusive with use_latest_message.
When true, marks the thread as read up to the latest message. Mutually exclusive with last_read_message.
89class ThreadPictureInputPicture(TypedDict): 90 data: str 91 "Base64-encoded binary content of the image file." 92 filename: str 93 'Original filename of the image, e.g. `"avatar.png"`. Used for storage and display.' 94 mime_type: str 95 'MIME type of the image, e.g. `"image/jpeg"` or `"image/png"`.'
98class ThreadPictureInput(TypedDict): 99 "Update a thread's profile picture" 100 101 picture: ThreadPictureInputPicture 102 "Profile picture payload. Must include the base64-encoded image data and its MIME type."
Update a thread's profile picture
Profile picture payload. Must include the base64-encoded image data and its MIME type.
105class ThreadMemberListResponseDataItemAgent(BaseModel): 106 email: str | None = Field( 107 default=None, description="Agent email address. `null` if not configured." 108 ) 109 id: str = Field(..., description="Agent ID (`agi_...`).") 110 name: str | None = Field( 111 default=None, description="Human-readable agent name. `null` if not set." 112 ) 113 org: str | None = Field( 114 default=None, 115 description="Organization that owns this agent (`org_...`). `null` if not org-scoped.", 116 ) 117 team: str | None = Field( 118 default=None, 119 description="Team that owns this agent (`tem_...`). `null` if not team-scoped.", 120 ) 121 user: str | None = Field( 122 default=None, 123 description="User that owns this agent (`usr_...`). `null` if not user-scoped.", 124 )
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized
__init__[Signature][inspect.Signature] of the model. - __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom
__init__function. - __pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces
Model.__validators__andModel.__root_validators__from Pydantic V1. - __pydantic_generic_metadata__: A dictionary containing metadata about generic Pydantic models.
The
originandargsitems map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and theparameteritem maps to the__parameter__attribute of generic classes. - __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [
RootModel][pydantic.root_model.RootModel]. - __pydantic_serializer__: The
pydantic-coreSchemaSerializerused to dump instances of the model. - __pydantic_validator__: The
pydantic-coreSchemaValidatorused to validate instances of the model. - __pydantic_fields__: A dictionary of field names and their corresponding [
FieldInfo][pydantic.fields.FieldInfo] objects. - __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [
ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects. - __pydantic_extra__: A dictionary containing extra values, if [
extra][pydantic.config.ConfigDict.extra] is set to'allow'. - __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.
127class ThreadMemberListResponseDataItemUser(BaseModel): 128 email: str | None = Field(default=None, description="User's email address. `null` if not set.") 129 full_name: str | None = Field( 130 default=None, description="Backward-compatible alias of `name`. `null` if not set." 131 ) 132 id: str = Field(..., description="User ID (`usr_...`).") 133 name: str | None = Field( 134 default=None, description="Full display name of the user. `null` if not set." 135 ) 136 org: str | None = Field( 137 default=None, 138 description="Organization this user belongs to (`org_...`). `null` if the user is not org-scoped.", 139 )
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized
__init__[Signature][inspect.Signature] of the model. - __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom
__init__function. - __pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces
Model.__validators__andModel.__root_validators__from Pydantic V1. - __pydantic_generic_metadata__: A dictionary containing metadata about generic Pydantic models.
The
originandargsitems map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and theparameteritem maps to the__parameter__attribute of generic classes. - __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [
RootModel][pydantic.root_model.RootModel]. - __pydantic_serializer__: The
pydantic-coreSchemaSerializerused to dump instances of the model. - __pydantic_validator__: The
pydantic-coreSchemaValidatorused to validate instances of the model. - __pydantic_fields__: A dictionary of field names and their corresponding [
FieldInfo][pydantic.fields.FieldInfo] objects. - __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [
ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects. - __pydantic_extra__: A dictionary containing extra values, if [
extra][pydantic.config.ConfigDict.extra] is set to'allow'. - __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.
142class ThreadMemberListResponseDataItem(BaseModel): 143 agent: ThreadMemberListResponseDataItemAgent | None = Field( 144 default=None, 145 description="Roster-safe agent identity. Populated for agent members; `null` for users.", 146 ) 147 joined_at: datetime | None = Field( 148 default=None, description="When this member joined the thread (ISO 8601)." 149 ) 150 member_type: str | None = Field( 151 default=None, description="Backward-compatible alias of `type`." 152 ) 153 membership_type: str | None = Field( 154 default=None, description='Role of this member, commonly `"owner"` or `"member"`.' 155 ) 156 role: str | None = Field( 157 default=None, description="Backward-compatible alias of `membership_type`." 158 ) 159 type: str = Field(..., description='Kind of participant. One of `"user"` or `"agent"`.') 160 user: ThreadMemberListResponseDataItemUser | None = Field( 161 default=None, 162 description="Roster-safe user identity. Populated for user members; `null` for agents.", 163 )
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized
__init__[Signature][inspect.Signature] of the model. - __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom
__init__function. - __pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces
Model.__validators__andModel.__root_validators__from Pydantic V1. - __pydantic_generic_metadata__: A dictionary containing metadata about generic Pydantic models.
The
originandargsitems map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and theparameteritem maps to the__parameter__attribute of generic classes. - __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [
RootModel][pydantic.root_model.RootModel]. - __pydantic_serializer__: The
pydantic-coreSchemaSerializerused to dump instances of the model. - __pydantic_validator__: The
pydantic-coreSchemaValidatorused to validate instances of the model. - __pydantic_fields__: A dictionary of field names and their corresponding [
FieldInfo][pydantic.fields.FieldInfo] objects. - __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [
ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects. - __pydantic_extra__: A dictionary containing extra values, if [
extra][pydantic.config.ConfigDict.extra] is set to'allow'. - __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.
166class ThreadMemberListResponse(BaseModel): 167 """ 168 Successful response 169 """ 170 171 data: list[ThreadMemberListResponseDataItem] = Field( 172 ..., 173 description="Array of thread member objects representing all current members of the thread.", 174 )
Successful response
177class SettingListResponse(BaseModel): 178 """ 179 Successful response 180 """ 181 182 agent_enabled: bool | None = Field( 183 default=None, 184 description="Whether the AI agent is active for this thread. Defaults to `true` when no settings have been explicitly set.", 185 )
Successful response
188class ThreadAgentsResponse(BaseModel): 189 """ 190 Successful response 191 """ 192 193 data: list[dict[str, Any]] = Field( 194 ..., 195 description="Array of agent objects for the thread. Each object includes `id`, `name`, `alias`, `profile_picture`, and `metadata`. Thread owners also receive an `agent_config` object with the agent's policy type and context configuration.", 196 )
Successful response
199class ThreadArtifactsResponseDataItemImageSource(BaseModel): 200 file: str | None = Field( 201 default=None, 202 description="ID of the underlying storage file (`fil_...`). `null` when the image is not backed by a platform storage file.", 203 ) 204 height: int | None = Field( 205 default=None, description="Height of the image in pixels. `null` if not known." 206 ) 207 media: str | None = Field( 208 default=None, 209 description="ID of the associated media record (`med_...`). `null` when the image is not linked to a media entity.", 210 ) 211 mime_type: str | None = Field( 212 default=None, 213 description='MIME type of the image, e.g. `"image/png"` or `"image/jpeg"`. `null` if not known.', 214 ) 215 refresh_url: str | None = Field( 216 default=None, 217 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.", 218 ) 219 url: str | None = Field( 220 default=None, 221 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.", 222 ) 223 width: int | None = Field( 224 default=None, description="Width of the image in pixels. `null` if not known." 225 )
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized
__init__[Signature][inspect.Signature] of the model. - __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom
__init__function. - __pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces
Model.__validators__andModel.__root_validators__from Pydantic V1. - __pydantic_generic_metadata__: A dictionary containing metadata about generic Pydantic models.
The
originandargsitems map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and theparameteritem maps to the__parameter__attribute of generic classes. - __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [
RootModel][pydantic.root_model.RootModel]. - __pydantic_serializer__: The
pydantic-coreSchemaSerializerused to dump instances of the model. - __pydantic_validator__: The
pydantic-coreSchemaValidatorused to validate instances of the model. - __pydantic_fields__: A dictionary of field names and their corresponding [
FieldInfo][pydantic.fields.FieldInfo] objects. - __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [
ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects. - __pydantic_extra__: A dictionary containing extra values, if [
extra][pydantic.config.ConfigDict.extra] is set to'allow'. - __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.
ID of the underlying storage file (fil_...). null when the image is not backed by a platform storage file.
ID of the associated media record (med_...). null when the image is not linked to a media entity.
MIME type of the image, e.g. "image/png" or "image/jpeg". null if not known.
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.
Signed or public URL for downloading the image. May be time-limited; use refresh_url to obtain a new URL when this one expires.
228class ThreadArtifactsResponseDataItem(BaseModel): 229 agent: str | None = Field( 230 default=None, 231 description="ID of the agent that produced this artifact (`agt_...`). `null` if not agent-produced.", 232 ) 233 content_type: str | None = Field( 234 default=None, 235 description='MIME type of the current version\'s file, e.g. `"text/csv"` or `"image/png"`. `null` if no file is attached.', 236 ) 237 created_at: datetime | None = Field( 238 default=None, description="When the artifact was first created (ISO 8601)." 239 ) 240 current_version: str | None = Field( 241 default=None, 242 description="ID of the current (latest published) artifact version (`artv_...`). `null` if no version has been published.", 243 ) 244 description: str | None = Field( 245 default=None, 246 description="Optional longer description of the artifact's contents or purpose. `null` if not set.", 247 ) 248 file: str | None = Field( 249 default=None, 250 description="Storage file ID for the current version (`fil_...`). `null` if no file is attached.", 251 ) 252 file_name: str | None = Field( 253 default=None, 254 description='Original filename of the current version\'s file, e.g. `"output.csv"`. `null` if no file is attached.', 255 ) 256 file_url: str | None = Field( 257 default=None, 258 description="Short-lived signed URL for downloading the current version's file. `null` if no file is attached.", 259 ) 260 id: str = Field(..., description="Artifact ID (`art_...`).") 261 image_source: ThreadArtifactsResponseDataItemImageSource | None = Field( 262 default=None, 263 description='Image source metadata for rendering the current version\'s file inline. Present only when `content_type` starts with `"image/"`. `null` otherwise.', 264 ) 265 name: str | None = Field( 266 default=None, 267 description='Human-readable name for the artifact, e.g. `"Q2 Report"`. `null` if not set.', 268 ) 269 org: str | None = Field( 270 default=None, description="ID of the organization this artifact belongs to (`org_...`)." 271 ) 272 sandbox: str | None = Field( 273 default=None, 274 description="Identifier of the sandbox environment associated with this artifact. `null` if not sandbox-scoped.", 275 ) 276 team: str | None = Field( 277 default=None, 278 description="ID of the team that owns this artifact (`tea_...`). `null` if not team-scoped.", 279 ) 280 thread: str | None = Field( 281 default=None, 282 description="ID of the thread in which this artifact was created (`thr_...`). `null` if not thread-scoped.", 283 ) 284 updated_at: datetime | None = Field( 285 default=None, description="When the artifact record was last modified (ISO 8601)." 286 ) 287 user: str | None = Field( 288 default=None, 289 description="ID of the user who created this artifact (`usr_...`). `null` if not user-scoped.", 290 ) 291 version: int | None = Field( 292 default=None, 293 description="Current version number of the artifact. Increments each time a new version is published.", 294 )
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized
__init__[Signature][inspect.Signature] of the model. - __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom
__init__function. - __pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces
Model.__validators__andModel.__root_validators__from Pydantic V1. - __pydantic_generic_metadata__: A dictionary containing metadata about generic Pydantic models.
The
originandargsitems map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and theparameteritem maps to the__parameter__attribute of generic classes. - __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [
RootModel][pydantic.root_model.RootModel]. - __pydantic_serializer__: The
pydantic-coreSchemaSerializerused to dump instances of the model. - __pydantic_validator__: The
pydantic-coreSchemaValidatorused to validate instances of the model. - __pydantic_fields__: A dictionary of field names and their corresponding [
FieldInfo][pydantic.fields.FieldInfo] objects. - __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [
ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects. - __pydantic_extra__: A dictionary containing extra values, if [
extra][pydantic.config.ConfigDict.extra] is set to'allow'. - __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.
ID of the agent that produced this artifact (agt_...). null if not agent-produced.
MIME type of the current version's file, e.g. "text/csv" or "image/png". null if no file is attached.
ID of the current (latest published) artifact version (artv_...). null if no version has been published.
Optional longer description of the artifact's contents or purpose. null if not set.
Storage file ID for the current version (fil_...). null if no file is attached.
Original filename of the current version's file, e.g. "output.csv". null if no file is attached.
Short-lived signed URL for downloading the current version's file. null if no file is attached.
Image source metadata for rendering the current version's file inline. Present only when content_type starts with "image/". null otherwise.
Identifier of the sandbox environment associated with this artifact. null if not sandbox-scoped.
ID of the thread in which this artifact was created (thr_...). null if not thread-scoped.
297class ThreadArtifactsResponse(BaseModel): 298 """ 299 Successful response 300 """ 301 302 data: list[ThreadArtifactsResponseDataItem] = Field( 303 ..., description="Array of artifact objects produced during the thread's conversation." 304 )
Successful response
307class ThreadMessagesResponseDataMessagesItemAclAddItem(BaseModel): 308 actions: list[str] = Field( 309 ..., 310 description='Array of action strings the principal is permitted to perform, e.g. `["read", "write"]`. Must contain at least one entry.', 311 ) 312 principal: str | None = Field( 313 default=None, 314 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"`.', 315 ) 316 principal_type: str = Field( 317 ..., 318 description='The kind of principal receiving the grant. One of `"user"`, `"team"`, `"org"`, `"org_role"`, `"agent"`, or `"everyone"`.', 319 )
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized
__init__[Signature][inspect.Signature] of the model. - __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom
__init__function. - __pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces
Model.__validators__andModel.__root_validators__from Pydantic V1. - __pydantic_generic_metadata__: A dictionary containing metadata about generic Pydantic models.
The
originandargsitems map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and theparameteritem maps to the__parameter__attribute of generic classes. - __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [
RootModel][pydantic.root_model.RootModel]. - __pydantic_serializer__: The
pydantic-coreSchemaSerializerused to dump instances of the model. - __pydantic_validator__: The
pydantic-coreSchemaValidatorused to validate instances of the model. - __pydantic_fields__: A dictionary of field names and their corresponding [
FieldInfo][pydantic.fields.FieldInfo] objects. - __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [
ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects. - __pydantic_extra__: A dictionary containing extra values, if [
extra][pydantic.config.ConfigDict.extra] is set to'allow'. - __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.
Array of action strings the principal is permitted to perform, e.g. ["read", "write"]. Must contain at least one entry.
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".
322class ThreadMessagesResponseDataMessagesItemAclGrantsItem(BaseModel): 323 actions: list[str] = Field( 324 ..., 325 description='Array of action strings the principal is permitted to perform, e.g. `["read", "write"]`. Must contain at least one entry.', 326 ) 327 principal: str | None = Field( 328 default=None, 329 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"`.', 330 ) 331 principal_type: str = Field( 332 ..., 333 description='The kind of principal receiving the grant. One of `"user"`, `"team"`, `"org"`, `"org_role"`, `"agent"`, or `"everyone"`.', 334 )
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized
__init__[Signature][inspect.Signature] of the model. - __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom
__init__function. - __pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces
Model.__validators__andModel.__root_validators__from Pydantic V1. - __pydantic_generic_metadata__: A dictionary containing metadata about generic Pydantic models.
The
originandargsitems map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and theparameteritem maps to the__parameter__attribute of generic classes. - __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [
RootModel][pydantic.root_model.RootModel]. - __pydantic_serializer__: The
pydantic-coreSchemaSerializerused to dump instances of the model. - __pydantic_validator__: The
pydantic-coreSchemaValidatorused to validate instances of the model. - __pydantic_fields__: A dictionary of field names and their corresponding [
FieldInfo][pydantic.fields.FieldInfo] objects. - __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [
ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects. - __pydantic_extra__: A dictionary containing extra values, if [
extra][pydantic.config.ConfigDict.extra] is set to'allow'. - __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.
Array of action strings the principal is permitted to perform, e.g. ["read", "write"]. Must contain at least one entry.
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".
337class ThreadMessagesResponseDataMessagesItemAclRemoveItem(BaseModel): 338 principal: str | None = Field( 339 default=None, 340 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"`.', 341 ) 342 principal_type: str = Field( 343 ..., 344 description='The kind of principal to remove. One of `"user"`, `"team"`, `"org"`, `"org_role"`, `"agent"`, or `"everyone"`.', 345 )
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized
__init__[Signature][inspect.Signature] of the model. - __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom
__init__function. - __pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces
Model.__validators__andModel.__root_validators__from Pydantic V1. - __pydantic_generic_metadata__: A dictionary containing metadata about generic Pydantic models.
The
originandargsitems map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and theparameteritem maps to the__parameter__attribute of generic classes. - __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [
RootModel][pydantic.root_model.RootModel]. - __pydantic_serializer__: The
pydantic-coreSchemaSerializerused to dump instances of the model. - __pydantic_validator__: The
pydantic-coreSchemaValidatorused to validate instances of the model. - __pydantic_fields__: A dictionary of field names and their corresponding [
FieldInfo][pydantic.fields.FieldInfo] objects. - __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [
ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects. - __pydantic_extra__: A dictionary containing extra values, if [
extra][pydantic.config.ConfigDict.extra] is set to'allow'. - __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.
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".
348class ThreadMessagesResponseDataMessagesItemAcl(BaseModel): 349 add: list[ThreadMessagesResponseDataMessagesItemAclAddItem] | None = Field( 350 default=None, 351 description="Patch mode: grants to add or merge into the existing list. Cannot be combined with `grants`.", 352 ) 353 grants: list[ThreadMessagesResponseDataMessagesItemAclGrantsItem] | None = Field( 354 default=None, 355 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`.", 356 ) 357 remove: list[ThreadMessagesResponseDataMessagesItemAclRemoveItem] | None = Field( 358 default=None, 359 description="Patch mode: principals whose grants should be removed from the existing list. Cannot be combined with `grants`.", 360 )
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized
__init__[Signature][inspect.Signature] of the model. - __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom
__init__function. - __pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces
Model.__validators__andModel.__root_validators__from Pydantic V1. - __pydantic_generic_metadata__: A dictionary containing metadata about generic Pydantic models.
The
originandargsitems map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and theparameteritem maps to the__parameter__attribute of generic classes. - __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [
RootModel][pydantic.root_model.RootModel]. - __pydantic_serializer__: The
pydantic-coreSchemaSerializerused to dump instances of the model. - __pydantic_validator__: The
pydantic-coreSchemaValidatorused to validate instances of the model. - __pydantic_fields__: A dictionary of field names and their corresponding [
FieldInfo][pydantic.fields.FieldInfo] objects. - __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [
ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects. - __pydantic_extra__: A dictionary containing extra values, if [
extra][pydantic.config.ConfigDict.extra] is set to'allow'. - __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.
Patch mode: grants to add or merge into the existing list. Cannot be combined with grants.
Patch mode: principals whose grants should be removed from the existing list. Cannot be combined with grants.
363class ThreadMessagesResponseDataMessagesItemActorsItemProfilePicture(BaseModel): 364 file: str | None = Field( 365 default=None, 366 description="ID of the underlying storage file (`fil_...`). `null` when the image is not backed by a platform storage file.", 367 ) 368 height: int | None = Field( 369 default=None, description="Height of the image in pixels. `null` if not known." 370 ) 371 media: str | None = Field( 372 default=None, 373 description="ID of the associated media record (`med_...`). `null` when the image is not linked to a media entity.", 374 ) 375 mime_type: str | None = Field( 376 default=None, 377 description='MIME type of the image, e.g. `"image/png"` or `"image/jpeg"`. `null` if not known.', 378 ) 379 refresh_url: str | None = Field( 380 default=None, 381 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.", 382 ) 383 url: str | None = Field( 384 default=None, 385 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.", 386 ) 387 width: int | None = Field( 388 default=None, description="Width of the image in pixels. `null` if not known." 389 )
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized
__init__[Signature][inspect.Signature] of the model. - __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom
__init__function. - __pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces
Model.__validators__andModel.__root_validators__from Pydantic V1. - __pydantic_generic_metadata__: A dictionary containing metadata about generic Pydantic models.
The
originandargsitems map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and theparameteritem maps to the__parameter__attribute of generic classes. - __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [
RootModel][pydantic.root_model.RootModel]. - __pydantic_serializer__: The
pydantic-coreSchemaSerializerused to dump instances of the model. - __pydantic_validator__: The
pydantic-coreSchemaValidatorused to validate instances of the model. - __pydantic_fields__: A dictionary of field names and their corresponding [
FieldInfo][pydantic.fields.FieldInfo] objects. - __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [
ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects. - __pydantic_extra__: A dictionary containing extra values, if [
extra][pydantic.config.ConfigDict.extra] is set to'allow'. - __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.
ID of the underlying storage file (fil_...). null when the image is not backed by a platform storage file.
ID of the associated media record (med_...). null when the image is not linked to a media entity.
MIME type of the image, e.g. "image/png" or "image/jpeg". null if not known.
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.
Signed or public URL for downloading the image. May be time-limited; use refresh_url to obtain a new URL when this one expires.
392class ThreadMessagesResponseDataMessagesItemActorsItem(BaseModel): 393 alias: str | None = Field( 394 default=None, 395 description="Short handle or alias for the actor, used as an alternate display identifier. `null` if not configured.", 396 ) 397 id: str | None = Field( 398 default=None, 399 description='Composite actor identifier. Format is `"user-<usr_...>"` for human users or `"agent-<agi_...>"` for agents.', 400 ) 401 name: str | None = Field( 402 default=None, 403 description="Display name of the actor shown in the UI. `null` if no name is set.", 404 ) 405 profile_picture: ThreadMessagesResponseDataMessagesItemActorsItemProfilePicture | None = Field( 406 default=None, 407 description="Profile picture for the actor. `null` if the actor has no profile picture.", 408 )
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized
__init__[Signature][inspect.Signature] of the model. - __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom
__init__function. - __pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces
Model.__validators__andModel.__root_validators__from Pydantic V1. - __pydantic_generic_metadata__: A dictionary containing metadata about generic Pydantic models.
The
originandargsitems map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and theparameteritem maps to the__parameter__attribute of generic classes. - __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [
RootModel][pydantic.root_model.RootModel]. - __pydantic_serializer__: The
pydantic-coreSchemaSerializerused to dump instances of the model. - __pydantic_validator__: The
pydantic-coreSchemaValidatorused to validate instances of the model. - __pydantic_fields__: A dictionary of field names and their corresponding [
FieldInfo][pydantic.fields.FieldInfo] objects. - __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [
ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects. - __pydantic_extra__: A dictionary containing extra values, if [
extra][pydantic.config.ConfigDict.extra] is set to'allow'. - __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.
Short handle or alias for the actor, used as an alternate display identifier. null if not configured.
Composite actor identifier. Format is "user-<usr_...>" for human users or "agent-<agi_...>" for agents.
411class ThreadMessagesResponseDataMessagesItemAttachmentsItemImageSource(BaseModel): 412 file: str | None = Field( 413 default=None, 414 description="ID of the underlying storage file (`fil_...`). `null` when the image is not backed by a platform storage file.", 415 ) 416 height: int | None = Field( 417 default=None, description="Height of the image in pixels. `null` if not known." 418 ) 419 media: str | None = Field( 420 default=None, 421 description="ID of the associated media record (`med_...`). `null` when the image is not linked to a media entity.", 422 ) 423 mime_type: str | None = Field( 424 default=None, 425 description='MIME type of the image, e.g. `"image/png"` or `"image/jpeg"`. `null` if not known.', 426 ) 427 refresh_url: str | None = Field( 428 default=None, 429 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.", 430 ) 431 url: str | None = Field( 432 default=None, 433 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.", 434 ) 435 width: int | None = Field( 436 default=None, description="Width of the image in pixels. `null` if not known." 437 )
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized
__init__[Signature][inspect.Signature] of the model. - __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom
__init__function. - __pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces
Model.__validators__andModel.__root_validators__from Pydantic V1. - __pydantic_generic_metadata__: A dictionary containing metadata about generic Pydantic models.
The
originandargsitems map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and theparameteritem maps to the__parameter__attribute of generic classes. - __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [
RootModel][pydantic.root_model.RootModel]. - __pydantic_serializer__: The
pydantic-coreSchemaSerializerused to dump instances of the model. - __pydantic_validator__: The
pydantic-coreSchemaValidatorused to validate instances of the model. - __pydantic_fields__: A dictionary of field names and their corresponding [
FieldInfo][pydantic.fields.FieldInfo] objects. - __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [
ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects. - __pydantic_extra__: A dictionary containing extra values, if [
extra][pydantic.config.ConfigDict.extra] is set to'allow'. - __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.
ID of the underlying storage file (fil_...). null when the image is not backed by a platform storage file.
ID of the associated media record (med_...). null when the image is not linked to a media entity.
MIME type of the image, e.g. "image/png" or "image/jpeg". null if not known.
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.
Signed or public URL for downloading the image. May be time-limited; use refresh_url to obtain a new URL when this one expires.
440class ThreadMessagesResponseDataMessagesItemAttachmentsItemVariantsItemImageSource(BaseModel): 441 file: str | None = Field( 442 default=None, 443 description="ID of the underlying storage file (`fil_...`). `null` when the image is not backed by a platform storage file.", 444 ) 445 height: int | None = Field( 446 default=None, description="Height of the image in pixels. `null` if not known." 447 ) 448 media: str | None = Field( 449 default=None, 450 description="ID of the associated media record (`med_...`). `null` when the image is not linked to a media entity.", 451 ) 452 mime_type: str | None = Field( 453 default=None, 454 description='MIME type of the image, e.g. `"image/png"` or `"image/jpeg"`. `null` if not known.', 455 ) 456 refresh_url: str | None = Field( 457 default=None, 458 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.", 459 ) 460 url: str | None = Field( 461 default=None, 462 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.", 463 ) 464 width: int | None = Field( 465 default=None, description="Width of the image in pixels. `null` if not known." 466 )
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized
__init__[Signature][inspect.Signature] of the model. - __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom
__init__function. - __pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces
Model.__validators__andModel.__root_validators__from Pydantic V1. - __pydantic_generic_metadata__: A dictionary containing metadata about generic Pydantic models.
The
originandargsitems map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and theparameteritem maps to the__parameter__attribute of generic classes. - __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [
RootModel][pydantic.root_model.RootModel]. - __pydantic_serializer__: The
pydantic-coreSchemaSerializerused to dump instances of the model. - __pydantic_validator__: The
pydantic-coreSchemaValidatorused to validate instances of the model. - __pydantic_fields__: A dictionary of field names and their corresponding [
FieldInfo][pydantic.fields.FieldInfo] objects. - __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [
ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects. - __pydantic_extra__: A dictionary containing extra values, if [
extra][pydantic.config.ConfigDict.extra] is set to'allow'. - __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.
ID of the underlying storage file (fil_...). null when the image is not backed by a platform storage file.
ID of the associated media record (med_...). null when the image is not linked to a media entity.
MIME type of the image, e.g. "image/png" or "image/jpeg". null if not known.
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.
Signed or public URL for downloading the image. May be time-limited; use refresh_url to obtain a new URL when this one expires.
469class ThreadMessagesResponseDataMessagesItemAttachmentsItemVariantsItem(BaseModel): 470 content_type: str | None = Field( 471 default=None, 472 description='MIME type of this variant\'s file (e.g., `"image/jpeg"`, `"video/mp4"`). `null` if the file is not loaded.', 473 ) 474 created_at: datetime | None = Field( 475 default=None, description="When this variant was created (ISO 8601)." 476 ) 477 file: str | None = Field( 478 default=None, 479 description="ID of the underlying storage file that backs this variant (`fil_...`).", 480 ) 481 filename: str | None = Field( 482 default=None, 483 description="Original filename of the uploaded file for this variant. `null` if the file is not loaded.", 484 ) 485 height: int | None = Field( 486 default=None, description="Height of this variant in pixels. `null` if not recorded." 487 ) 488 id: str = Field(..., description="Media variant ID (`mvr_...`).") 489 image_source: ( 490 ThreadMessagesResponseDataMessagesItemAttachmentsItemVariantsItemImageSource | None 491 ) = Field( 492 default=None, 493 description="Resolved image delivery metadata for this variant, including dimensions and CDN URL. `null` for non-image content types.", 494 ) 495 updated_at: datetime | None = Field( 496 default=None, description="When this variant was last updated (ISO 8601)." 497 ) 498 url: str | None = Field( 499 default=None, 500 description="Signed download URL for this variant, resolved at request time. `null` if the file is unavailable.", 501 ) 502 variant_key: str | None = Field( 503 default=None, 504 description='Identifier for this variant\'s processing tier. Common values include `"original"` (the unmodified upload) and `"thumbnail"` (a resized preview).', 505 ) 506 width: int | None = Field( 507 default=None, description="Width of this variant in pixels. `null` if not recorded." 508 )
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized
__init__[Signature][inspect.Signature] of the model. - __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom
__init__function. - __pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces
Model.__validators__andModel.__root_validators__from Pydantic V1. - __pydantic_generic_metadata__: A dictionary containing metadata about generic Pydantic models.
The
originandargsitems map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and theparameteritem maps to the__parameter__attribute of generic classes. - __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [
RootModel][pydantic.root_model.RootModel]. - __pydantic_serializer__: The
pydantic-coreSchemaSerializerused to dump instances of the model. - __pydantic_validator__: The
pydantic-coreSchemaValidatorused to validate instances of the model. - __pydantic_fields__: A dictionary of field names and their corresponding [
FieldInfo][pydantic.fields.FieldInfo] objects. - __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [
ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects. - __pydantic_extra__: A dictionary containing extra values, if [
extra][pydantic.config.ConfigDict.extra] is set to'allow'. - __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.
MIME type of this variant's file (e.g., "image/jpeg", "video/mp4"). null if the file is not loaded.
Original filename of the uploaded file for this variant. null if the file is not loaded.
Resolved image delivery metadata for this variant, including dimensions and CDN URL. null for non-image content types.
Signed download URL for this variant, resolved at request time. null if the file is unavailable.
511class ThreadMessagesResponseDataMessagesItemAttachmentsItem(BaseModel): 512 content_type: str | None = Field( 513 default=None, 514 description='MIME type of the attached file, e.g. `"image/png"` or `"application/pdf"`. Present on `file`, `artifact`, and `media` types. `null` otherwise.', 515 ) 516 description: str | None = Field( 517 default=None, 518 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.", 519 ) 520 filename: str | None = Field( 521 default=None, 522 description='Original filename of the attached file, e.g. `"report.pdf"`. Present on `file`, `artifact`, and `media` types. `null` otherwise.', 523 ) 524 height: int | None = Field( 525 default=None, 526 description="Height in pixels of the media item. Present on `media` type only. `null` otherwise.", 527 ) 528 id: str = Field(..., description="Unique identifier for this attachment within the message.") 529 image_height: int | None = Field( 530 default=None, 531 description="Height in pixels of the scraped preview image. Present on `scraped_link` type only. `null` otherwise.", 532 ) 533 image_source: ThreadMessagesResponseDataMessagesItemAttachmentsItemImageSource | None = Field( 534 default=None, 535 description="Image source metadata for inline rendering. Present on `file`, `scraped_link`, `artifact`, and `media` types when the content is an image. `null` otherwise.", 536 ) 537 image_url: str | None = Field( 538 default=None, 539 description="URL of the preview image extracted from the scraped page. Present on `scraped_link` type only. `null` otherwise.", 540 ) 541 image_width: int | None = Field( 542 default=None, 543 description="Width in pixels of the scraped preview image. Present on `scraped_link` type only. `null` otherwise.", 544 ) 545 media_type: str | None = Field( 546 default=None, 547 description='The media category, e.g. `"video"` or `"audio"`. Present on `media` type only; omitted otherwise.', 548 ) 549 name: str | None = Field( 550 default=None, 551 description="Display name of the media item. Present on `media` type only. `null` otherwise.", 552 ) 553 object: dict[str, Any] | None = Field( 554 default=None, 555 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.", 556 ) 557 title: str | None = Field( 558 default=None, 559 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.", 560 ) 561 type: str = Field( 562 ..., 563 description='The attachment type. One of `"file"`, `"scraped_link"`, `"artifact"`, `"task"`, `"media"`, `"action"`, or `"chart"`. Determines which additional fields are present.', 564 ) 565 url: str | None = Field( 566 default=None, 567 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.", 568 ) 569 variants: list[ThreadMessagesResponseDataMessagesItemAttachmentsItemVariantsItem] | None = ( 570 Field( 571 default=None, 572 description="Array of available encoding variants for the media item (e.g. different resolutions). Present on `media` type only; omitted otherwise.", 573 ) 574 ) 575 version: int | None = Field( 576 default=None, 577 description="Version number of the attached artifact at the time of attachment. Present on `artifact` type only. `null` otherwise.", 578 ) 579 width: int | None = Field( 580 default=None, 581 description="Width in pixels of the media item. Present on `media` type only. `null` otherwise.", 582 )
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized
__init__[Signature][inspect.Signature] of the model. - __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom
__init__function. - __pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces
Model.__validators__andModel.__root_validators__from Pydantic V1. - __pydantic_generic_metadata__: A dictionary containing metadata about generic Pydantic models.
The
originandargsitems map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and theparameteritem maps to the__parameter__attribute of generic classes. - __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [
RootModel][pydantic.root_model.RootModel]. - __pydantic_serializer__: The
pydantic-coreSchemaSerializerused to dump instances of the model. - __pydantic_validator__: The
pydantic-coreSchemaValidatorused to validate instances of the model. - __pydantic_fields__: A dictionary of field names and their corresponding [
FieldInfo][pydantic.fields.FieldInfo] objects. - __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [
ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects. - __pydantic_extra__: A dictionary containing extra values, if [
extra][pydantic.config.ConfigDict.extra] is set to'allow'. - __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.
MIME type of the attached file, e.g. "image/png" or "application/pdf". Present on file, artifact, and media types. null otherwise.
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.
Original filename of the attached file, e.g. "report.pdf". Present on file, artifact, and media types. null otherwise.
Height in pixels of the media item. Present on media type only. null otherwise.
Height in pixels of the scraped preview image. Present on scraped_link type only. null otherwise.
Image source metadata for inline rendering. Present on file, scraped_link, artifact, and media types when the content is an image. null otherwise.
URL of the preview image extracted from the scraped page. Present on scraped_link type only. null otherwise.
Width in pixels of the scraped preview image. Present on scraped_link type only. null otherwise.
The media category, e.g. "video" or "audio". Present on media type only; omitted otherwise.
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.
Display title. The page title for scraped_link, the artifact name for artifact, and the task title for task types. null on other types.
The attachment type. One of "file", "scraped_link", "artifact", "task", "media", "action", or "chart". Determines which additional fields are present.
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.
Array of available encoding variants for the media item (e.g. different resolutions). Present on media type only; omitted otherwise.
585class ThreadMessagesResponseDataMessagesItemReactionsItem(BaseModel): 586 payload: dict[str, Any] | None = Field( 587 default=None, 588 description='Type-specific reaction data. For `"emoji_reaction"` reactions, contains an `emoji` key with the Unicode emoji string (e.g., `" "`).', 589 ) 590 type: str = Field( 591 ..., 592 description='Reaction type identifier. Currently always `"emoji_reaction"` for emoji-based reactions.', 593 ) 594 user: str | None = Field( 595 default=None, description="Public ID of the user who added the reaction (`usr_...`)." 596 )
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized
__init__[Signature][inspect.Signature] of the model. - __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom
__init__function. - __pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces
Model.__validators__andModel.__root_validators__from Pydantic V1. - __pydantic_generic_metadata__: A dictionary containing metadata about generic Pydantic models.
The
originandargsitems map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and theparameteritem maps to the__parameter__attribute of generic classes. - __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [
RootModel][pydantic.root_model.RootModel]. - __pydantic_serializer__: The
pydantic-coreSchemaSerializerused to dump instances of the model. - __pydantic_validator__: The
pydantic-coreSchemaValidatorused to validate instances of the model. - __pydantic_fields__: A dictionary of field names and their corresponding [
FieldInfo][pydantic.fields.FieldInfo] objects. - __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [
ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects. - __pydantic_extra__: A dictionary containing extra values, if [
extra][pydantic.config.ConfigDict.extra] is set to'allow'. - __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.
Type-specific reaction data. For "emoji_reaction" reactions, contains an emoji key with the Unicode emoji string (e.g., " ").
599class ThreadMessagesResponseDataMessagesItem(BaseModel): 600 acl: ThreadMessagesResponseDataMessagesItemAcl | None = Field( 601 default=None, 602 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.", 603 ) 604 actors: list[ThreadMessagesResponseDataMessagesItemActorsItem] | None = Field( 605 default=None, 606 description="Resolved actor descriptors for the message sender, combining identity and display metadata. Always contains exactly one entry.", 607 ) 608 agent: str | None = Field( 609 default=None, 610 description="ID of the agent user that sent this message (`agi_...`). `null` for messages sent by human users.", 611 ) 612 agent_mode: Literal["cli", "embedded"] | None = Field( 613 default=None, 614 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.", 615 ) 616 attachments: list[ThreadMessagesResponseDataMessagesItemAttachmentsItem] | None = Field( 617 default=None, 618 description="Files, links, tasks, media, artifacts, and actions attached to this message. Empty array if there are no attachments.", 619 ) 620 branched_thread: str | None = Field( 621 default=None, 622 description="ID of the thread that was branched from this message (`thr_...`). `null` if this message has not spawned a branch thread.", 623 ) 624 content: str | None = Field( 625 default=None, 626 description="Text content of the message. `null` for messages that contain only attachments.", 627 ) 628 created_at: str | None = Field( 629 default=None, description="When the message was posted (ISO 8601)." 630 ) 631 has_replies: bool | None = Field( 632 default=None, 633 description="Whether this message has at least one reply. Only present when explicitly requested or computed by the server.", 634 ) 635 id: str = Field(..., description="Message ID (`msg_...`).") 636 idempotency_key: str | None = Field( 637 default=None, 638 description="Client-supplied idempotency key used to deduplicate message sends. `null` if the sender did not provide one.", 639 ) 640 is_deleted: bool | None = Field( 641 default=None, 642 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.", 643 ) 644 legacy_agent: str | None = Field( 645 default=None, 646 description="Identifier of the legacy chat agent that sent this message, if applicable. `null` for messages sent by users or modern agent users.", 647 ) 648 metadata: dict[str, Any] | None = Field( 649 default=None, 650 description="Arbitrary key-value metadata attached to the message. Always present; defaults to an empty object when no metadata has been set.", 651 ) 652 org: str | None = Field( 653 default=None, description="ID of the organization that owns this message (`org_...`)." 654 ) 655 reactions: list[ThreadMessagesResponseDataMessagesItemReactionsItem] | None = Field( 656 default=None, 657 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.", 658 ) 659 rendering_mode: str | None = Field( 660 default=None, 661 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.', 662 ) 663 replies: list[dict[str, Any]] | None = Field( 664 default=None, 665 description="Inline array of reply messages, each serialized as a full message object. Only present when the server has preloaded replies for this message.", 666 ) 667 replies_after_cursor: str | None = Field( 668 default=None, 669 description="Opaque pagination cursor to fetch replies posted after the current page. Only present when inline replies are included in the response.", 670 ) 671 replies_before_cursor: str | None = Field( 672 default=None, 673 description="Opaque pagination cursor to fetch replies posted before the current page. Only present when inline replies are included in the response.", 674 ) 675 reply_count: int | None = Field( 676 default=None, 677 description="Total number of direct replies to this message. Only present when explicitly requested or computed by the server.", 678 ) 679 reply_to: dict[str, Any] | None = Field( 680 default=None, 681 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.", 682 ) 683 root_message_id: str | None = Field( 684 default=None, 685 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.", 686 ) 687 sandbox: str | None = Field( 688 default=None, 689 description="ID of the developer sandbox this message belongs to (`dsb_...`). `null` for non-sandbox messages.", 690 ) 691 team: str | None = Field( 692 default=None, 693 description="ID of the team this message is scoped to (`tem_...`). `null` if the message is not team-scoped.", 694 ) 695 thread: str | None = Field( 696 default=None, description="ID of the thread this message belongs to (`thr_...`)." 697 ) 698 type: str | None = Field( 699 default=None, 700 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.", 701 ) 702 user: str | dict[str, Any] | None = Field( 703 default=None, 704 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.", 705 ) 706 visibility: Literal["default", "private"] | None = Field( 707 default=None, 708 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.", 709 )
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized
__init__[Signature][inspect.Signature] of the model. - __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom
__init__function. - __pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces
Model.__validators__andModel.__root_validators__from Pydantic V1. - __pydantic_generic_metadata__: A dictionary containing metadata about generic Pydantic models.
The
originandargsitems map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and theparameteritem maps to the__parameter__attribute of generic classes. - __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [
RootModel][pydantic.root_model.RootModel]. - __pydantic_serializer__: The
pydantic-coreSchemaSerializerused to dump instances of the model. - __pydantic_validator__: The
pydantic-coreSchemaValidatorused to validate instances of the model. - __pydantic_fields__: A dictionary of field names and their corresponding [
FieldInfo][pydantic.fields.FieldInfo] objects. - __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [
ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects. - __pydantic_extra__: A dictionary containing extra values, if [
extra][pydantic.config.ConfigDict.extra] is set to'allow'. - __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.
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.
Resolved actor descriptors for the message sender, combining identity and display metadata. Always contains exactly one entry.
ID of the agent user that sent this message (agi_...). null for messages sent by human users.
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.
Files, links, tasks, media, artifacts, and actions attached to this message. Empty array if there are no attachments.
ID of the thread that was branched from this message (thr_...). null if this message has not spawned a branch thread.
Text content of the message. null for messages that contain only attachments.
Whether this message has at least one reply. Only present when explicitly requested or computed by the server.
Client-supplied idempotency key used to deduplicate message sends. null if the sender did not provide one.
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.
Identifier of the legacy chat agent that sent this message, if applicable. null for messages sent by users or modern agent users.
Arbitrary key-value metadata attached to the message. Always present; defaults to an empty object when no metadata has been set.
Emoji and other reactions added to this message by users. Empty array if no reactions have been added or the association is not preloaded.
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.
Inline array of reply messages, each serialized as a full message object. Only present when the server has preloaded replies for this message.
Opaque pagination cursor to fetch replies posted after the current page. Only present when inline replies are included in the response.
Opaque pagination cursor to fetch replies posted before the current page. Only present when inline replies are included in the response.
Total number of direct replies to this message. Only present when explicitly requested or computed by the server.
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.
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.
ID of the developer sandbox this message belongs to (dsb_...). null for non-sandbox messages.
ID of the team this message is scoped to (tem_...). null if the message is not team-scoped.
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.
712class ThreadMessagesResponseData(BaseModel): 713 after_cursor: str | None = Field( 714 default=None, 715 description="Opaque cursor to pass as `after` to retrieve the page of messages newer than this result set. `null` when there are no later messages.", 716 ) 717 anchor: str | None = Field( 718 default=None, 719 description="Message ID used as the anchor for a windowed query. `null` for ordinary cursor pagination.", 720 ) 721 before_cursor: str | None = Field( 722 default=None, 723 description="Opaque cursor to pass as `before` to retrieve the page of messages older than this result set. `null` when there are no earlier messages.", 724 ) 725 messages: list[ThreadMessagesResponseDataMessagesItem] = Field( 726 ..., description="Ordered array of message objects for this page of results." 727 )
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized
__init__[Signature][inspect.Signature] of the model. - __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom
__init__function. - __pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces
Model.__validators__andModel.__root_validators__from Pydantic V1. - __pydantic_generic_metadata__: A dictionary containing metadata about generic Pydantic models.
The
originandargsitems map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and theparameteritem maps to the__parameter__attribute of generic classes. - __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [
RootModel][pydantic.root_model.RootModel]. - __pydantic_serializer__: The
pydantic-coreSchemaSerializerused to dump instances of the model. - __pydantic_validator__: The
pydantic-coreSchemaValidatorused to validate instances of the model. - __pydantic_fields__: A dictionary of field names and their corresponding [
FieldInfo][pydantic.fields.FieldInfo] objects. - __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [
ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects. - __pydantic_extra__: A dictionary containing extra values, if [
extra][pydantic.config.ConfigDict.extra] is set to'allow'. - __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.
Opaque cursor to pass as after to retrieve the page of messages newer than this result set. null when there are no later messages.
Message ID used as the anchor for a windowed query. null for ordinary cursor pagination.
Opaque cursor to pass as before to retrieve the page of messages older than this result set. null when there are no earlier messages.
730class ThreadMessagesResponse(BaseModel): 731 """ 732 Successful response 733 """ 734 735 data: ThreadMessagesResponseData = Field( 736 ..., 737 description="Pagination envelope containing the messages for this page along with cursors for adjacent pages.", 738 )
Successful response
741class ThreadSearchResponseDataItem(BaseModel): 742 agent: str | None = Field( 743 default=None, 744 description="Agent sender ID (`agi_...`), or `null` when a human sent the message.", 745 ) 746 content: str = Field( 747 ..., 748 description="A bounded snippet around the first matching occurrence (at most 240 characters).", 749 ) 750 created_at: datetime = Field(..., description="When the message was posted.") 751 id: str = Field(..., description="Message ID (`msg_...`).") 752 similarity_score: float | None = Field( 753 default=None, 754 description="Cosine similarity to the query when the result participated in embedding search, or `null` in text mode and for text-only hybrid matches.", 755 ) 756 user: str | None = Field( 757 default=None, 758 description="Human sender ID (`usr_...`), or `null` when an agent sent the message.", 759 )
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized
__init__[Signature][inspect.Signature] of the model. - __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom
__init__function. - __pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces
Model.__validators__andModel.__root_validators__from Pydantic V1. - __pydantic_generic_metadata__: A dictionary containing metadata about generic Pydantic models.
The
originandargsitems map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and theparameteritem maps to the__parameter__attribute of generic classes. - __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [
RootModel][pydantic.root_model.RootModel]. - __pydantic_serializer__: The
pydantic-coreSchemaSerializerused to dump instances of the model. - __pydantic_validator__: The
pydantic-coreSchemaValidatorused to validate instances of the model. - __pydantic_fields__: A dictionary of field names and their corresponding [
FieldInfo][pydantic.fields.FieldInfo] objects. - __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [
ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects. - __pydantic_extra__: A dictionary containing extra values, if [
extra][pydantic.config.ConfigDict.extra] is set to'allow'. - __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.
A bounded snippet around the first matching occurrence (at most 240 characters).
762class ThreadSearchResponse(BaseModel): 763 """ 764 Successful response 765 """ 766 767 after_cursor: str | None = Field( 768 default=None, 769 description="Text-mode cursor for the next page of newer matches, or `null` for ranked modes and empty pages.", 770 ) 771 before_cursor: str | None = Field( 772 default=None, 773 description="Text-mode cursor for the next page of older matches, or `null` for ranked modes and empty pages.", 774 ) 775 data: list[ThreadSearchResponseDataItem] = Field( 776 ..., 777 description="Matching messages ordered newest first in text mode and by relevance in embedding or hybrid mode.", 778 ) 779 has_more: bool = Field( 780 ..., description="`true` when at least one additional visible match exists." 781 )
Successful response
Text-mode cursor for the next page of newer matches, or null for ranked modes and empty pages.
Text-mode cursor for the next page of older matches, or null for ranked modes and empty pages.
784class ThreadTrajectoriesResponseDataItem(BaseModel): 785 agent_message: str | None = Field( 786 default=None, 787 description="ID of the agent-authored reply message (`msg_...`). `null` if the trajectory has not yet produced a response message.", 788 ) 789 created_at: str | None = Field( 790 default=None, description="When this trajectory link was created (ISO 8601)." 791 ) 792 id: str = Field(..., description="Thread message trajectory ID (`tmt_...`).") 793 org: str | None = Field( 794 default=None, description="ID of the organization this trajectory belongs to (`org_...`)." 795 ) 796 sandbox: str | None = Field( 797 default=None, 798 description="ID of the sandbox environment in which this trajectory was produced (`dsb_...`). `null` in production contexts.", 799 ) 800 thread: str | None = Field( 801 default=None, description="ID of the thread containing the linked messages (`thr_...`)." 802 ) 803 trajectory: str | None = Field( 804 default=None, 805 description="ID of the AI trajectory record that captures the full model interaction for this exchange (`trj_...`).", 806 ) 807 updated_at: str | None = Field( 808 default=None, description="When this trajectory link was last modified (ISO 8601)." 809 ) 810 user_message: str | None = Field( 811 default=None, 812 description="ID of the user-authored message that triggered the agent response (`msg_...`). `null` if the agent turn was not preceded by a user message.", 813 )
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized
__init__[Signature][inspect.Signature] of the model. - __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom
__init__function. - __pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces
Model.__validators__andModel.__root_validators__from Pydantic V1. - __pydantic_generic_metadata__: A dictionary containing metadata about generic Pydantic models.
The
originandargsitems map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and theparameteritem maps to the__parameter__attribute of generic classes. - __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [
RootModel][pydantic.root_model.RootModel]. - __pydantic_serializer__: The
pydantic-coreSchemaSerializerused to dump instances of the model. - __pydantic_validator__: The
pydantic-coreSchemaValidatorused to validate instances of the model. - __pydantic_fields__: A dictionary of field names and their corresponding [
FieldInfo][pydantic.fields.FieldInfo] objects. - __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [
ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects. - __pydantic_extra__: A dictionary containing extra values, if [
extra][pydantic.config.ConfigDict.extra] is set to'allow'. - __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.
ID of the agent-authored reply message (msg_...). null if the trajectory has not yet produced a response message.
ID of the sandbox environment in which this trajectory was produced (dsb_...). null in production contexts.
816class ThreadTrajectoriesResponse(BaseModel): 817 """ 818 Successful response 819 """ 820 821 after_cursor: str | None = Field( 822 default=None, 823 description="Opaque cursor to pass as `after_cursor` to retrieve the next page. `null` when no further pages exist.", 824 ) 825 before_cursor: str | None = Field( 826 default=None, 827 description="Opaque cursor to pass as `before_cursor` to retrieve the previous page. `null` when this is the first page.", 828 ) 829 data: list[ThreadTrajectoriesResponseDataItem] = Field( 830 ..., 831 description="Array of thread message trajectory objects for the current page. Empty when no trajectories match the query.", 832 )
Successful response
Opaque cursor to pass as after_cursor to retrieve the next page. null when no further pages exist.
Opaque cursor to pass as before_cursor to retrieve the previous page. null when this is the first page.
835class AsyncThreadMemberResource: 836 def __init__(self, http: HttpClient): 837 self._http = http 838 839 async def remove(self, thread: str) -> None: 840 """ 841 Remove a member from a thread 842 Removes a user or agent from the explicit roster of a private or restricted 843 thread. Team-visible threads use implicit membership and reject individual 844 removals. A member may remove themself; removing someone else requires 845 permission to modify the thread. A successful removal returns HTTP 204 with 846 no response body. 847 Supply either `user` or `agent` depending on the value of `type`. Returns 404 848 if the thread or the membership record does not exist. 849 850 Args: 851 thread: Thread ID (`thr_...`) identifying the thread to remove the member from. 852 853 Returns: 854 Empty response body. HTTP 204 on success. 855 """ 856 await self._http.request(f"/api/v1/threads/{thread}/members", method="DELETE") 857 858 async def list(self, thread: str) -> ThreadMemberListResponse: 859 """ 860 List members of a thread 861 Returns all current user and agent members. Private and restricted threads 862 return their explicit roster; team-visible threads return the owning team's 863 implicit roster. The authenticated viewer must be able to see the thread. 864 Results are returned as a flat array in the `data` field. The list is not 865 paginated all members are returned in a single response. 866 867 Args: 868 thread: Thread ID (`thr_...`) identifying the thread to remove the member from. 869 870 Returns: 871 Successful response 872 """ 873 return await self._http.request( 874 f"/api/v1/threads/{thread}/members", 875 response_type=ThreadMemberListResponse, 876 ) 877 878 async def create(self, thread: str, input: ThreadMemberCreateInput) -> ChatMember: 879 """ 880 Add a member to a thread 881 Adds a user or agent to the explicit roster of a private or restricted 882 thread. Team-visible threads use the owning team's implicit roster and reject 883 explicit additions. On restricted threads, a team member may add themself; 884 adding anyone else requires permission to modify the thread. 885 Supply either `user` or `agent` depending on the value of `type`. Targets 886 must be visible to the caller and, for an ordinary team-owned thread, must 887 belong to the owning team. On success the membership record is returned with 888 HTTP 201; repeated agent additions are idempotent. 889 890 Args: 891 thread: Thread ID (`thr_...`) identifying the thread to remove the member from. 892 input: Request body. 893 input.agent: Agent ID of the principal to add. Required when `type` is `"agent"`. 894 input.membership_type: Role granted to the new member. One of `"owner"` or `"member"`. Defaults to `"member"`. 895 input.type: Kind of principal being added. Must be `"user"` or `"agent"`. 896 input.user: User ID of the principal to add. Required when `type` is `"user"`. 897 898 Returns: 899 The user or agent membership that was added to the thread. 900 """ 901 return await self._http.request( 902 f"/api/v1/threads/{thread}/members", 903 method="POST", 904 body=input, 905 response_type=ChatMember, 906 )
839 async def remove(self, thread: str) -> None: 840 """ 841 Remove a member from a thread 842 Removes a user or agent from the explicit roster of a private or restricted 843 thread. Team-visible threads use implicit membership and reject individual 844 removals. A member may remove themself; removing someone else requires 845 permission to modify the thread. A successful removal returns HTTP 204 with 846 no response body. 847 Supply either `user` or `agent` depending on the value of `type`. Returns 404 848 if the thread or the membership record does not exist. 849 850 Args: 851 thread: Thread ID (`thr_...`) identifying the thread to remove the member from. 852 853 Returns: 854 Empty response body. HTTP 204 on success. 855 """ 856 await self._http.request(f"/api/v1/threads/{thread}/members", method="DELETE")
Remove a member from a thread
Removes a user or agent from the explicit roster of a private or restricted
thread. Team-visible threads use implicit membership and reject individual
removals. A member may remove themself; removing someone else requires
permission to modify the thread. A successful removal returns HTTP 204 with
no response body.
Supply either user or agent depending on the value of type. Returns 404
if the thread or the membership record does not exist.
Arguments:
- thread: Thread ID (
thr_...) identifying the thread to remove the member from.
Returns:
Empty response body. HTTP 204 on success.
858 async def list(self, thread: str) -> ThreadMemberListResponse: 859 """ 860 List members of a thread 861 Returns all current user and agent members. Private and restricted threads 862 return their explicit roster; team-visible threads return the owning team's 863 implicit roster. The authenticated viewer must be able to see the thread. 864 Results are returned as a flat array in the `data` field. The list is not 865 paginated all members are returned in a single response. 866 867 Args: 868 thread: Thread ID (`thr_...`) identifying the thread to remove the member from. 869 870 Returns: 871 Successful response 872 """ 873 return await self._http.request( 874 f"/api/v1/threads/{thread}/members", 875 response_type=ThreadMemberListResponse, 876 )
List members of a thread
Returns all current user and agent members. Private and restricted threads
return their explicit roster; team-visible threads return the owning team's
implicit roster. The authenticated viewer must be able to see the thread.
Results are returned as a flat array in the data field. The list is not
paginated all members are returned in a single response.
Arguments:
- thread: Thread ID (
thr_...) identifying the thread to remove the member from.
Returns:
Successful response
878 async def create(self, thread: str, input: ThreadMemberCreateInput) -> ChatMember: 879 """ 880 Add a member to a thread 881 Adds a user or agent to the explicit roster of a private or restricted 882 thread. Team-visible threads use the owning team's implicit roster and reject 883 explicit additions. On restricted threads, a team member may add themself; 884 adding anyone else requires permission to modify the thread. 885 Supply either `user` or `agent` depending on the value of `type`. Targets 886 must be visible to the caller and, for an ordinary team-owned thread, must 887 belong to the owning team. On success the membership record is returned with 888 HTTP 201; repeated agent additions are idempotent. 889 890 Args: 891 thread: Thread ID (`thr_...`) identifying the thread to remove the member from. 892 input: Request body. 893 input.agent: Agent ID of the principal to add. Required when `type` is `"agent"`. 894 input.membership_type: Role granted to the new member. One of `"owner"` or `"member"`. Defaults to `"member"`. 895 input.type: Kind of principal being added. Must be `"user"` or `"agent"`. 896 input.user: User ID of the principal to add. Required when `type` is `"user"`. 897 898 Returns: 899 The user or agent membership that was added to the thread. 900 """ 901 return await self._http.request( 902 f"/api/v1/threads/{thread}/members", 903 method="POST", 904 body=input, 905 response_type=ChatMember, 906 )
Add a member to a thread
Adds a user or agent to the explicit roster of a private or restricted
thread. Team-visible threads use the owning team's implicit roster and reject
explicit additions. On restricted threads, a team member may add themself;
adding anyone else requires permission to modify the thread.
Supply either user or agent depending on the value of type. Targets
must be visible to the caller and, for an ordinary team-owned thread, must
belong to the owning team. On success the membership record is returned with
HTTP 201; repeated agent additions are idempotent.
Arguments:
- thread: Thread ID (
thr_...) identifying the thread to remove the member from. - input: Request body.
- input.agent: Agent ID of the principal to add. Required when
typeis"agent". - input.membership_type: Role granted to the new member. One of
"owner"or"member". Defaults to"member". - input.type: Kind of principal being added. Must be
"user"or"agent". - input.user: User ID of the principal to add. Required when
typeis"user".
Returns:
The user or agent membership that was added to the thread.
909class AsyncSettingResource: 910 def __init__(self, http: HttpClient): 911 self._http = http 912 913 async def list(self, thread: str) -> SettingListResponse: 914 """ 915 Retrieve thread settings 916 Returns the current settings for the specified thread. Settings control 917 per-thread behavior such as whether the AI agent is enabled. 918 The authenticated user must own the thread or be a member of its workspace. 919 If settings have never been explicitly configured, defaults are returned 920 (for example, `agent_enabled` defaults to `true`). 921 922 Args: 923 thread: Thread ID (`thr_...`). Must belong to the authenticated user's workspace. 924 925 Returns: 926 Successful response 927 """ 928 return await self._http.request( 929 f"/api/v1/threads/{thread}/settings", 930 response_type=SettingListResponse, 931 ) 932 933 async def replace(self, thread: str, input: SettingReplaceInput) -> ThreadSettings: 934 """ 935 Update thread settings 936 Updates the settings for the specified thread. Only fields included in 937 the `settings` map are modified; omitted fields retain their current values. 938 The authenticated user must own the thread or be a member of its workspace. 939 Returns the full settings object reflecting the state after the update. 940 Validation errors are returned as `422 Unprocessable Entity`. 941 942 Args: 943 thread: Thread ID (`thr_...`). Must belong to the authenticated user's workspace. 944 input: Request body. 945 input.settings: Map of settings fields to update. Include only the keys you want to change. 946 947 Returns: 948 The thread settings object after the update has been applied. 949 """ 950 return await self._http.request( 951 f"/api/v1/threads/{thread}/settings", 952 method="PUT", 953 body=input, 954 response_type=ThreadSettings, 955 )
913 async def list(self, thread: str) -> SettingListResponse: 914 """ 915 Retrieve thread settings 916 Returns the current settings for the specified thread. Settings control 917 per-thread behavior such as whether the AI agent is enabled. 918 The authenticated user must own the thread or be a member of its workspace. 919 If settings have never been explicitly configured, defaults are returned 920 (for example, `agent_enabled` defaults to `true`). 921 922 Args: 923 thread: Thread ID (`thr_...`). Must belong to the authenticated user's workspace. 924 925 Returns: 926 Successful response 927 """ 928 return await self._http.request( 929 f"/api/v1/threads/{thread}/settings", 930 response_type=SettingListResponse, 931 )
Retrieve thread settings
Returns the current settings for the specified thread. Settings control
per-thread behavior such as whether the AI agent is enabled.
The authenticated user must own the thread or be a member of its workspace.
If settings have never been explicitly configured, defaults are returned
(for example, agent_enabled defaults to true).
Arguments:
- thread: Thread ID (
thr_...). Must belong to the authenticated user's workspace.
Returns:
Successful response
933 async def replace(self, thread: str, input: SettingReplaceInput) -> ThreadSettings: 934 """ 935 Update thread settings 936 Updates the settings for the specified thread. Only fields included in 937 the `settings` map are modified; omitted fields retain their current values. 938 The authenticated user must own the thread or be a member of its workspace. 939 Returns the full settings object reflecting the state after the update. 940 Validation errors are returned as `422 Unprocessable Entity`. 941 942 Args: 943 thread: Thread ID (`thr_...`). Must belong to the authenticated user's workspace. 944 input: Request body. 945 input.settings: Map of settings fields to update. Include only the keys you want to change. 946 947 Returns: 948 The thread settings object after the update has been applied. 949 """ 950 return await self._http.request( 951 f"/api/v1/threads/{thread}/settings", 952 method="PUT", 953 body=input, 954 response_type=ThreadSettings, 955 )
Update thread settings
Updates the settings for the specified thread. Only fields included in
the settings map are modified; omitted fields retain their current values.
The authenticated user must own the thread or be a member of its workspace.
Returns the full settings object reflecting the state after the update.
Validation errors are returned as 422 Unprocessable Entity.
Arguments:
- thread: Thread ID (
thr_...). Must belong to the authenticated user's workspace. - input: Request body.
- input.settings: Map of settings fields to update. Include only the keys you want to change.
Returns:
The thread settings object after the update has been applied.
958class AsyncTagResource: 959 def __init__(self, http: HttpClient): 960 self._http = http 961 962 async def remove(self, thread: str) -> Thread: 963 """ 964 Remove tags from a thread 965 Removes one or more status tags from the thread and returns the updated 966 thread. Removing a tag the thread does not have is a no-op. 967 Any participant of the thread a human member or an agent member may edit 968 tags. Supply the tags to remove as repeated query parameters, e.g. 969 `?tags[]=blocked&tags[]=needs-review`. 970 971 Args: 972 thread: Thread ID (`thr_...`) to untag. 973 974 Returns: 975 The thread object after the tags were removed. 976 """ 977 return await self._http.request( 978 f"/api/v1/threads/{thread}/tags", 979 method="DELETE", 980 response_type=Thread, 981 ) 982 983 async def create(self, thread: str, input: TagCreateInput) -> Thread: 984 """ 985 Add tags to a thread 986 Adds one or more status tags to the thread and returns the updated thread. 987 Any participant of the thread a human member or an agent member may edit 988 tags; this is broader than the owner/admin permission required to update other 989 thread fields. Adding a tag the thread already has is a no-op. Tags are 990 normalized (trimmed and lowercased) and may contain only lowercase letters, 991 numbers, hyphens, and underscores. 992 993 Args: 994 thread: Thread ID (`thr_...`) to untag. 995 input: Request body. 996 input.tags: Tags to add to the thread. 997 998 Returns: 999 The thread object after the tags were added. 1000 """ 1001 return await self._http.request( 1002 f"/api/v1/threads/{thread}/tags", 1003 method="POST", 1004 body=input, 1005 response_type=Thread, 1006 ) 1007 1008 async def replace(self, thread: str, input: TagReplaceInput) -> Thread: 1009 """ 1010 Replace a thread's tags 1011 Replaces the thread's entire set of status tags with the provided list and 1012 returns the updated thread. Passing an empty array clears all tags. 1013 Any participant of the thread a human member or an agent member may edit 1014 tags. Tags are normalized (trimmed and lowercased) and may contain only 1015 lowercase letters, numbers, hyphens, and underscores. 1016 1017 Args: 1018 thread: Thread ID (`thr_...`) to untag. 1019 input: Request body. 1020 input.tags: The complete set of tags for the thread. An empty array clears all tags. 1021 1022 Returns: 1023 The thread object after its tags were replaced. 1024 """ 1025 return await self._http.request( 1026 f"/api/v1/threads/{thread}/tags", 1027 method="PUT", 1028 body=input, 1029 response_type=Thread, 1030 )
962 async def remove(self, thread: str) -> Thread: 963 """ 964 Remove tags from a thread 965 Removes one or more status tags from the thread and returns the updated 966 thread. Removing a tag the thread does not have is a no-op. 967 Any participant of the thread a human member or an agent member may edit 968 tags. Supply the tags to remove as repeated query parameters, e.g. 969 `?tags[]=blocked&tags[]=needs-review`. 970 971 Args: 972 thread: Thread ID (`thr_...`) to untag. 973 974 Returns: 975 The thread object after the tags were removed. 976 """ 977 return await self._http.request( 978 f"/api/v1/threads/{thread}/tags", 979 method="DELETE", 980 response_type=Thread, 981 )
Remove tags from a thread
Removes one or more status tags from the thread and returns the updated
thread. Removing a tag the thread does not have is a no-op.
Any participant of the thread a human member or an agent member may edit
tags. Supply the tags to remove as repeated query parameters, e.g.
?tags[]=blocked&tags[]=needs-review.
Arguments:
- thread: Thread ID (
thr_...) to untag.
Returns:
The thread object after the tags were removed.
983 async def create(self, thread: str, input: TagCreateInput) -> Thread: 984 """ 985 Add tags to a thread 986 Adds one or more status tags to the thread and returns the updated thread. 987 Any participant of the thread a human member or an agent member may edit 988 tags; this is broader than the owner/admin permission required to update other 989 thread fields. Adding a tag the thread already has is a no-op. Tags are 990 normalized (trimmed and lowercased) and may contain only lowercase letters, 991 numbers, hyphens, and underscores. 992 993 Args: 994 thread: Thread ID (`thr_...`) to untag. 995 input: Request body. 996 input.tags: Tags to add to the thread. 997 998 Returns: 999 The thread object after the tags were added. 1000 """ 1001 return await self._http.request( 1002 f"/api/v1/threads/{thread}/tags", 1003 method="POST", 1004 body=input, 1005 response_type=Thread, 1006 )
Add tags to a thread Adds one or more status tags to the thread and returns the updated thread. Any participant of the thread a human member or an agent member may edit tags; this is broader than the owner/admin permission required to update other thread fields. Adding a tag the thread already has is a no-op. Tags are normalized (trimmed and lowercased) and may contain only lowercase letters, numbers, hyphens, and underscores.
Arguments:
- thread: Thread ID (
thr_...) to untag. - input: Request body.
- input.tags: Tags to add to the thread.
Returns:
The thread object after the tags were added.
1008 async def replace(self, thread: str, input: TagReplaceInput) -> Thread: 1009 """ 1010 Replace a thread's tags 1011 Replaces the thread's entire set of status tags with the provided list and 1012 returns the updated thread. Passing an empty array clears all tags. 1013 Any participant of the thread a human member or an agent member may edit 1014 tags. Tags are normalized (trimmed and lowercased) and may contain only 1015 lowercase letters, numbers, hyphens, and underscores. 1016 1017 Args: 1018 thread: Thread ID (`thr_...`) to untag. 1019 input: Request body. 1020 input.tags: The complete set of tags for the thread. An empty array clears all tags. 1021 1022 Returns: 1023 The thread object after its tags were replaced. 1024 """ 1025 return await self._http.request( 1026 f"/api/v1/threads/{thread}/tags", 1027 method="PUT", 1028 body=input, 1029 response_type=Thread, 1030 )
Replace a thread's tags Replaces the thread's entire set of status tags with the provided list and returns the updated thread. Passing an empty array clears all tags. Any participant of the thread a human member or an agent member may edit tags. Tags are normalized (trimmed and lowercased) and may contain only lowercase letters, numbers, hyphens, and underscores.
Arguments:
- thread: Thread ID (
thr_...) to untag. - input: Request body.
- input.tags: The complete set of tags for the thread. An empty array clears all tags.
Returns:
The thread object after its tags were replaced.
1033class AsyncThreadResource: 1034 def __init__(self, http: HttpClient): 1035 self._http = http 1036 self.members = AsyncThreadMemberResource(http) 1037 self.settings = AsyncSettingResource(http) 1038 self.tags = AsyncTagResource(http) 1039 1040 async def delete(self, thread: str) -> None: 1041 """ 1042 Delete a thread 1043 Permanently deletes a thread and all of its messages and artifacts. This action 1044 cannot be undone. 1045 The authenticated user must own the thread or be an owner of the team the thread 1046 belongs to. Attempting to delete a thread owned by another user or team returns 403. 1047 1048 Args: 1049 thread: Thread ID (`thr_...`). The authenticated user must own this thread. 1050 1051 Returns: 1052 Empty response on successful deletion. 1053 """ 1054 await self._http.request(f"/api/v1/threads/{thread}", method="DELETE") 1055 1056 async def get(self, thread: str) -> Thread: 1057 """ 1058 Retrieve a thread 1059 Returns the full thread record for the given thread ID. The authenticated user 1060 must own the thread or be a member of the workspace it belongs to. 1061 Use this endpoint to fetch the current state of a single thread, including its 1062 title, description, and metadata. To list many threads, use the list endpoint 1063 with cursor-based pagination. 1064 1065 Args: 1066 thread: Thread ID (`thr_...`). The authenticated user must have access to this thread. 1067 1068 Returns: 1069 The requested thread object. 1070 """ 1071 return await self._http.request(f"/api/v1/threads/{thread}", response_type=Thread) 1072 1073 async def replace(self, thread: str, input: ThreadReplaceInput) -> Thread: 1074 """ 1075 Update a thread 1076 Updates one or more mutable properties of the specified thread and returns 1077 the full thread object with the applied changes. Only the fields you provide 1078 are modified; omitted fields retain their current values. 1079 If `profile_picture` is supplied, the image is uploaded before the other 1080 fields are saved, after all ordinary thread fields have passed validation. 1081 Supplying invalid base64 picture data returns 422 and no other fields are 1082 updated. 1083 Visibility can only widen: `private` may become `restricted` or `team`, and 1084 `restricted` may become `team`. The authenticated viewer must have 1085 permission to modify the thread. 1086 Mirror-thread titles, descriptions, and notification state remain editable 1087 by privileged app viewers. Mirror metadata, visibility, and membership are 1088 provider-managed and cannot be changed through this endpoint. 1089 1090 Args: 1091 thread: Thread ID (`thr_...`). The authenticated user must have permission to update this thread. 1092 input: Request body. 1093 input.description: Optional longer text describing the thread's purpose. Replaces the existing description when provided. 1094 input.metadata: Arbitrary key-value metadata to store on the thread. Merged with or replaces existing metadata. 1095 input.muted: When `true`, suppresses notifications for new messages in this thread for the authenticated user. 1096 input.profile_picture: New profile picture for the thread. Provide all three inner fields to replace the existing image. 1097 input.title: Human-readable display name for the thread. Replaces the existing title when provided. 1098 input.visibility: Widen a team-owned thread: `private` may become `restricted` or `team`, and `restricted` may become `team`. Visibility cannot be narrowed. 1099 1100 Returns: 1101 The thread object after the update has been applied. 1102 """ 1103 return await self._http.request( 1104 f"/api/v1/threads/{thread}", 1105 method="PUT", 1106 body=input, 1107 response_type=Thread, 1108 ) 1109 1110 async def agents(self, thread: str) -> ThreadAgentsResponse: 1111 """ 1112 List agents in a thread 1113 Returns the agents participating in the specified thread. Only personal user 1114 threads (threads owned by a single user, not a team) expose agents through 1115 this endpoint; requests for team threads return 404. 1116 The authenticated user must have visibility into the thread. Each agent entry 1117 includes display information such as name and profile picture. Thread-level 1118 overrides (e.g. a custom name or profile picture set for this thread) take 1119 precedence over the agent's default values. When the caller is the thread 1120 owner, each entry also includes an `agent_config` object describing the 1121 agent's message policy and context configuration. 1122 1123 Args: 1124 thread: Thread ID (`thr_...`). Must be a personal user thread visible to the authenticated user. 1125 1126 Returns: 1127 Successful response 1128 """ 1129 return await self._http.request( 1130 f"/api/v1/threads/{thread}/agents", 1131 response_type=ThreadAgentsResponse, 1132 ) 1133 1134 async def artifacts(self, thread: str) -> ThreadArtifactsResponse: 1135 """ 1136 List artifacts for a thread 1137 Returns all artifacts produced during a thread's AI conversation. Artifacts are 1138 structured outputs such as code files, documents, or generated assets created 1139 by the AI agent in response to messages in the thread. 1140 The authenticated user must have access to the specified thread. Results are 1141 returned in a single page; there is no cursor-based pagination for this endpoint. 1142 1143 Args: 1144 thread: Thread ID (`thr_...`). Must be accessible to the authenticated user. 1145 1146 Returns: 1147 Successful response 1148 """ 1149 return await self._http.request( 1150 f"/api/v1/threads/{thread}/artifacts", 1151 response_type=ThreadArtifactsResponse, 1152 ) 1153 1154 async def mark_read(self, thread: str, input: ThreadMarkReadInput) -> None: 1155 """ 1156 Mark a thread as read 1157 Records that a user has read up to a specific message in the thread. Unread 1158 indicators and badge counts are cleared up to the specified message. 1159 You must supply exactly one of `last_read_message` or `use_latest_message`. 1160 Omitting both returns 400. If `use_latest_message` is `true` and the thread 1161 has no messages, the request succeeds silently with no state change. 1162 For server-to-server (S2S) requests where no user identity is present in the 1163 token, the `user` param is required to identify whose read state to update. 1164 1165 Args: 1166 thread: Thread ID (`thr_...`). The thread to mark as read. 1167 input: Request body. 1168 input.last_read_message: Message ID (`msg_...`) to record as the last read message. Mutually exclusive with `use_latest_message`. 1169 input.use_latest_message: When `true`, marks the thread as read up to the latest message. Mutually exclusive with `last_read_message`. 1170 input.user: User ID (`usr_...`) whose read state to update. Required for S2S requests; ignored when an authenticated user is present in the token. 1171 1172 Returns: 1173 Empty response on success. 1174 """ 1175 await self._http.request(f"/api/v1/threads/{thread}/mark_read", method="POST", body=input) 1176 1177 async def messages( 1178 self, 1179 thread: str, 1180 *, 1181 before_cursor: str | None = None, 1182 after_cursor: str | None = None, 1183 metadata: dict[str, Any] | None = None, 1184 limit: int | None = None, 1185 anchor: str | None = None, 1186 direction: Literal["before", "after", "around"] | None = None, 1187 before_limit: int | None = None, 1188 after_limit: int | None = None, 1189 include_anchor: bool | None = None, 1190 anchor_agent_mode: Literal["cli", "embedded"] | None = None, 1191 anchor_agent: str | None = None, 1192 include_reply_counts: bool | None = None, 1193 ) -> ThreadMessagesResponse: 1194 """ 1195 List messages in a thread 1196 Returns a cursor-paginated list of messages belonging to the specified thread, 1197 ordered from oldest to newest. Supply `before_cursor`, `after_cursor`, or both 1198 to page through or bound the result set; omit both to receive the most recent page. 1199 Supply `anchor` and `direction` to fetch a window before, after, or around a 1200 specific message. Use `anchor=last_matching&anchor_agent_mode=embedded` to 1201 resolve the anchor from the latest embedded-agent message, and add 1202 `anchor_agent` to scope that resolution to a single sender agent. 1203 Supply `metadata` as a JSON-encoded structured expression to filter message 1204 metadata before cursor pagination or anchored window limits are applied. 1205 The authenticated user must have access to the thread's owner (workspace or user). 1206 A 403 is returned if the thread exists but is not accessible to the caller; a 404 1207 is returned if the thread does not exist or is not visible to the authenticated user. 1208 Pass `include_reply_counts: true` to annotate each message with the number of 1209 threaded replies it has received. This adds a small amount of latency and should 1210 be omitted when reply counts are not needed. 1211 1212 Args: 1213 thread: Thread ID (`thr_...`). The authenticated user must have access to this thread. 1214 before_cursor: Opaque cursor returned in a previous response's `before_cursor` field. When provided, returns messages immediately before that position. May be combined with `after_cursor` to bound a range. 1215 after_cursor: Opaque cursor returned in a previous response's `after_cursor` field. When provided, returns messages immediately after that position. May be combined with `before_cursor` to bound a range. 1216 metadata: Structured metadata filter expression. Only messages whose `metadata` object satisfies the expression are returned. The filter is applied before cursor pagination and anchored window limits. 1217 limit: Maximum number of messages to return per page. Defaults to 20; maximum is 100. 1218 anchor: Message ID (`msg_...`) to use as a window anchor, or `last_matching` to resolve the anchor from the latest message matching the anchor filters. Cannot be combined with `before_cursor` or `after_cursor`. 1219 direction: Window direction relative to `anchor`. `before` returns older messages, `after` returns newer messages, and `around` returns messages on both sides. Defaults to `after` when `anchor` is supplied. `direction=around` cannot be combined with an explicit `limit`; use `before_limit` and `after_limit`. 1220 before_limit: For `direction=around`, maximum number of messages older than the anchor. Defaults to 20; maximum is 100. 1221 after_limit: For `direction=around`, maximum number of messages newer than the anchor. Defaults to 20; maximum is 100. 1222 include_anchor: Whether to include the anchor message in a window response. Defaults to `true` for `direction=around`; ignored for ordinary cursor pagination and one-sided windows. 1223 anchor_agent_mode: When `anchor=last_matching`, resolve the anchor from the latest message with this local agent execution mode. 1224 anchor_agent: When `anchor=last_matching`, scope the anchor resolution to messages sent by this agent (`agi_...`). Combine with `anchor_agent_mode` to resolve the latest message from a specific agent in a given mode. 1225 include_reply_counts: When `true`, each message in the response is annotated with its threaded reply count. Defaults to `false`. Adds latency; omit when reply counts are not needed. 1226 1227 Returns: 1228 Successful response 1229 """ 1230 query: dict[str, object] = {} 1231 if before_cursor is not None: 1232 query["before_cursor"] = before_cursor 1233 if after_cursor is not None: 1234 query["after_cursor"] = after_cursor 1235 if metadata is not None: 1236 query["metadata"] = metadata 1237 if limit is not None: 1238 query["limit"] = limit 1239 if anchor is not None: 1240 query["anchor"] = anchor 1241 if direction is not None: 1242 query["direction"] = direction 1243 if before_limit is not None: 1244 query["before_limit"] = before_limit 1245 if after_limit is not None: 1246 query["after_limit"] = after_limit 1247 if include_anchor is not None: 1248 query["include_anchor"] = include_anchor 1249 if anchor_agent_mode is not None: 1250 query["anchor_agent_mode"] = anchor_agent_mode 1251 if anchor_agent is not None: 1252 query["anchor_agent"] = anchor_agent 1253 if include_reply_counts is not None: 1254 query["include_reply_counts"] = include_reply_counts 1255 return await self._http.request( 1256 f"/api/v1/threads/{thread}/messages", 1257 query=query, 1258 response_type=ThreadMessagesResponse, 1259 ) 1260 1261 async def picture(self, thread: str, input: ThreadPictureInput) -> Thread: 1262 """ 1263 Update a thread's profile picture 1264 Uploads a new profile picture for the specified thread and returns the updated 1265 thread object. The image must be supplied as a base64-encoded string with its 1266 MIME type. 1267 The authenticated user must own the thread or be a team owner of the workspace 1268 the thread belongs to. Supplying invalid base64 data returns 422. 1269 1270 Args: 1271 thread: Thread ID (`thr_...`). The authenticated user must have permission to update this thread. 1272 input: Request body. 1273 input.picture: Profile picture payload. Must include the base64-encoded image data and its MIME type. 1274 1275 Returns: 1276 The thread object after the profile picture has been updated. 1277 """ 1278 return await self._http.request( 1279 f"/api/v1/threads/{thread}/picture", 1280 method="PUT", 1281 body=input, 1282 response_type=Thread, 1283 ) 1284 1285 async def read_status(self, thread: str, *, user: str | None = None) -> ThreadReadStatus: 1286 """ 1287 Retrieve a thread's read status 1288 Returns the read status of a thread for the specified user, including the ID 1289 of the last message they have read and the number of unread messages remaining. 1290 For user-authenticated requests, the status is always returned for the 1291 authenticated user and the `user` parameter is ignored. For server-to-server 1292 (S2S) requests, the `user` parameter is required and must be a valid user ID. 1293 Returns 404 if the thread does not exist or the caller does not have access 1294 to it. 1295 1296 Args: 1297 thread: Thread ID (`thr_...`). Must be accessible to the authenticated user or, for S2S requests, to the specified user. 1298 user: User ID (`usr_...`) whose read status to retrieve. Required for S2S requests; ignored for user-authenticated requests, which always return the status for the authenticated user. 1299 1300 Returns: 1301 The read status record for the requested thread and user. 1302 """ 1303 query: dict[str, object] = {} 1304 if user is not None: 1305 query["user"] = user 1306 return await self._http.request( 1307 f"/api/v1/threads/{thread}/read_status", 1308 query=query, 1309 response_type=ThreadReadStatus, 1310 ) 1311 1312 async def search( 1313 self, 1314 thread: str, 1315 q: str, 1316 *, 1317 app: str | None = None, 1318 limit: int | None = None, 1319 mode: Literal["text", "embedding", "hybrid"] | None = None, 1320 before_cursor: str | None = None, 1321 after_cursor: str | None = None, 1322 ) -> ThreadSearchResponse: 1323 """ 1324 Search messages in a thread 1325 Searches canonical message content in the specified thread. `"text"` mode 1326 performs the existing case-insensitive substring search, `"embedding"` ranks 1327 stored message embeddings by cosine similarity, and `"hybrid"` combines the 1328 text and embedding rankings with Reciprocal Rank Fusion (RRF). Only messages 1329 visible to the authenticated caller are considered. 1330 Results are intentionally lean: each row contains only a bounded content 1331 snippet, sender identity, and timestamp. Attachments, reactions, ACLs, and 1332 metadata are neither hydrated nor serialized. At most 20 results are 1333 returned. Text results support chronological cursor pagination. Embedding and 1334 hybrid results are relevance-ranked single pages and return null cursors. 1335 1336 Args: 1337 thread: Thread ID (`thr_...`). Must be visible to the authenticated caller. 1338 app: App ID (`app_...`). Required by the protected developer mount and omitted from the public mount. 1339 q: Text or semantic search query. Must contain 3 to 200 characters after trimming. 1340 limit: Maximum number of results. Defaults to 20 and is capped at 20. 1341 mode: Search algorithm: `text` for substring matching, `embedding` for cosine similarity, or `hybrid` for RRF over both rankings. 1342 before_cursor: Text mode only. Opaque cursor returned by a previous page; fetches older matches. 1343 after_cursor: Text mode only. Opaque cursor returned by a previous page; fetches newer matches. 1344 1345 Returns: 1346 Successful response 1347 """ 1348 query: dict[str, object] = {} 1349 if app is not None: 1350 query["app"] = app 1351 query["q"] = q 1352 if limit is not None: 1353 query["limit"] = limit 1354 if mode is not None: 1355 query["mode"] = mode 1356 if before_cursor is not None: 1357 query["before_cursor"] = before_cursor 1358 if after_cursor is not None: 1359 query["after_cursor"] = after_cursor 1360 return await self._http.request( 1361 f"/api/v1/threads/{thread}/search", 1362 query=query, 1363 response_type=ThreadSearchResponse, 1364 ) 1365 1366 async def trajectories( 1367 self, 1368 thread: str, 1369 *, 1370 before_cursor: str | None = None, 1371 after_cursor: str | None = None, 1372 limit: int | None = None, 1373 message: str | None = None, 1374 ) -> ThreadTrajectoriesResponse: 1375 """ 1376 List trajectories for a thread 1377 Returns a cursor-paginated list of thread message trajectories associated with the 1378 specified thread. Each trajectory links a user message and its agent response to the 1379 underlying AI trajectory record that captured the model's reasoning steps. 1380 The authenticated user must own the thread or be a member of the workspace it belongs 1381 to. Results are returned in reverse chronological order by default. Use `before_cursor` 1382 and `after_cursor` to navigate pages; provide at most one cursor per request. 1383 Optionally filter results to trajectories produced in response to a specific message 1384 by supplying the `message` parameter. When no trajectories match the query, `data` 1385 is an empty array and both cursor fields are `null`. A cursor that cannot be decoded 1386 returns a 400 `invalid_cursor` error. 1387 1388 Args: 1389 thread: Thread ID (`thr_...`). The authenticated user must own this thread or belong to its workspace. 1390 before_cursor: Opaque cursor from a previous response's `before_cursor` field. Returns the page of results preceding that cursor position. 1391 after_cursor: Opaque cursor from a previous response's `after_cursor` field. Returns the page of results following that cursor position. 1392 limit: Maximum number of trajectories to return per page. Defaults to 20; maximum is 100. 1393 message: Message ID (`msg_...`). When provided, limits results to trajectories associated with this specific message. 1394 1395 Returns: 1396 Successful response 1397 """ 1398 query: dict[str, object] = {} 1399 if before_cursor is not None: 1400 query["before_cursor"] = before_cursor 1401 if after_cursor is not None: 1402 query["after_cursor"] = after_cursor 1403 if limit is not None: 1404 query["limit"] = limit 1405 if message is not None: 1406 query["message"] = message 1407 return await self._http.request( 1408 f"/api/v1/threads/{thread}/trajectories", 1409 query=query, 1410 response_type=ThreadTrajectoriesResponse, 1411 )
1040 async def delete(self, thread: str) -> None: 1041 """ 1042 Delete a thread 1043 Permanently deletes a thread and all of its messages and artifacts. This action 1044 cannot be undone. 1045 The authenticated user must own the thread or be an owner of the team the thread 1046 belongs to. Attempting to delete a thread owned by another user or team returns 403. 1047 1048 Args: 1049 thread: Thread ID (`thr_...`). The authenticated user must own this thread. 1050 1051 Returns: 1052 Empty response on successful deletion. 1053 """ 1054 await self._http.request(f"/api/v1/threads/{thread}", method="DELETE")
Delete a thread Permanently deletes a thread and all of its messages and artifacts. This action cannot be undone. The authenticated user must own the thread or be an owner of the team the thread belongs to. Attempting to delete a thread owned by another user or team returns 403.
Arguments:
- thread: Thread ID (
thr_...). The authenticated user must own this thread.
Returns:
Empty response on successful deletion.
1056 async def get(self, thread: str) -> Thread: 1057 """ 1058 Retrieve a thread 1059 Returns the full thread record for the given thread ID. The authenticated user 1060 must own the thread or be a member of the workspace it belongs to. 1061 Use this endpoint to fetch the current state of a single thread, including its 1062 title, description, and metadata. To list many threads, use the list endpoint 1063 with cursor-based pagination. 1064 1065 Args: 1066 thread: Thread ID (`thr_...`). The authenticated user must have access to this thread. 1067 1068 Returns: 1069 The requested thread object. 1070 """ 1071 return await self._http.request(f"/api/v1/threads/{thread}", response_type=Thread)
Retrieve a thread Returns the full thread record for the given thread ID. The authenticated user must own the thread or be a member of the workspace it belongs to. Use this endpoint to fetch the current state of a single thread, including its title, description, and metadata. To list many threads, use the list endpoint with cursor-based pagination.
Arguments:
- thread: Thread ID (
thr_...). The authenticated user must have access to this thread.
Returns:
The requested thread object.
1073 async def replace(self, thread: str, input: ThreadReplaceInput) -> Thread: 1074 """ 1075 Update a thread 1076 Updates one or more mutable properties of the specified thread and returns 1077 the full thread object with the applied changes. Only the fields you provide 1078 are modified; omitted fields retain their current values. 1079 If `profile_picture` is supplied, the image is uploaded before the other 1080 fields are saved, after all ordinary thread fields have passed validation. 1081 Supplying invalid base64 picture data returns 422 and no other fields are 1082 updated. 1083 Visibility can only widen: `private` may become `restricted` or `team`, and 1084 `restricted` may become `team`. The authenticated viewer must have 1085 permission to modify the thread. 1086 Mirror-thread titles, descriptions, and notification state remain editable 1087 by privileged app viewers. Mirror metadata, visibility, and membership are 1088 provider-managed and cannot be changed through this endpoint. 1089 1090 Args: 1091 thread: Thread ID (`thr_...`). The authenticated user must have permission to update this thread. 1092 input: Request body. 1093 input.description: Optional longer text describing the thread's purpose. Replaces the existing description when provided. 1094 input.metadata: Arbitrary key-value metadata to store on the thread. Merged with or replaces existing metadata. 1095 input.muted: When `true`, suppresses notifications for new messages in this thread for the authenticated user. 1096 input.profile_picture: New profile picture for the thread. Provide all three inner fields to replace the existing image. 1097 input.title: Human-readable display name for the thread. Replaces the existing title when provided. 1098 input.visibility: Widen a team-owned thread: `private` may become `restricted` or `team`, and `restricted` may become `team`. Visibility cannot be narrowed. 1099 1100 Returns: 1101 The thread object after the update has been applied. 1102 """ 1103 return await self._http.request( 1104 f"/api/v1/threads/{thread}", 1105 method="PUT", 1106 body=input, 1107 response_type=Thread, 1108 )
Update a thread
Updates one or more mutable properties of the specified thread and returns
the full thread object with the applied changes. Only the fields you provide
are modified; omitted fields retain their current values.
If profile_picture is supplied, the image is uploaded before the other
fields are saved, after all ordinary thread fields have passed validation.
Supplying invalid base64 picture data returns 422 and no other fields are
updated.
Visibility can only widen: private may become restricted or team, and
restricted may become team. The authenticated viewer must have
permission to modify the thread.
Mirror-thread titles, descriptions, and notification state remain editable
by privileged app viewers. Mirror metadata, visibility, and membership are
provider-managed and cannot be changed through this endpoint.
Arguments:
- thread: Thread ID (
thr_...). The authenticated user must have permission to update this thread. - input: Request body.
- input.description: Optional longer text describing the thread's purpose. Replaces the existing description when provided.
- input.metadata: Arbitrary key-value metadata to store on the thread. Merged with or replaces existing metadata.
- input.muted: When
true, suppresses notifications for new messages in this thread for the authenticated user. - input.profile_picture: New profile picture for the thread. Provide all three inner fields to replace the existing image.
- input.title: Human-readable display name for the thread. Replaces the existing title when provided.
- input.visibility: Widen a team-owned thread:
privatemay becomerestrictedorteam, andrestrictedmay becometeam. Visibility cannot be narrowed.
Returns:
The thread object after the update has been applied.
1110 async def agents(self, thread: str) -> ThreadAgentsResponse: 1111 """ 1112 List agents in a thread 1113 Returns the agents participating in the specified thread. Only personal user 1114 threads (threads owned by a single user, not a team) expose agents through 1115 this endpoint; requests for team threads return 404. 1116 The authenticated user must have visibility into the thread. Each agent entry 1117 includes display information such as name and profile picture. Thread-level 1118 overrides (e.g. a custom name or profile picture set for this thread) take 1119 precedence over the agent's default values. When the caller is the thread 1120 owner, each entry also includes an `agent_config` object describing the 1121 agent's message policy and context configuration. 1122 1123 Args: 1124 thread: Thread ID (`thr_...`). Must be a personal user thread visible to the authenticated user. 1125 1126 Returns: 1127 Successful response 1128 """ 1129 return await self._http.request( 1130 f"/api/v1/threads/{thread}/agents", 1131 response_type=ThreadAgentsResponse, 1132 )
List agents in a thread
Returns the agents participating in the specified thread. Only personal user
threads (threads owned by a single user, not a team) expose agents through
this endpoint; requests for team threads return 404.
The authenticated user must have visibility into the thread. Each agent entry
includes display information such as name and profile picture. Thread-level
overrides (e.g. a custom name or profile picture set for this thread) take
precedence over the agent's default values. When the caller is the thread
owner, each entry also includes an agent_config object describing the
agent's message policy and context configuration.
Arguments:
- thread: Thread ID (
thr_...). Must be a personal user thread visible to the authenticated user.
Returns:
Successful response
1134 async def artifacts(self, thread: str) -> ThreadArtifactsResponse: 1135 """ 1136 List artifacts for a thread 1137 Returns all artifacts produced during a thread's AI conversation. Artifacts are 1138 structured outputs such as code files, documents, or generated assets created 1139 by the AI agent in response to messages in the thread. 1140 The authenticated user must have access to the specified thread. Results are 1141 returned in a single page; there is no cursor-based pagination for this endpoint. 1142 1143 Args: 1144 thread: Thread ID (`thr_...`). Must be accessible to the authenticated user. 1145 1146 Returns: 1147 Successful response 1148 """ 1149 return await self._http.request( 1150 f"/api/v1/threads/{thread}/artifacts", 1151 response_type=ThreadArtifactsResponse, 1152 )
List artifacts for a thread Returns all artifacts produced during a thread's AI conversation. Artifacts are structured outputs such as code files, documents, or generated assets created by the AI agent in response to messages in the thread. The authenticated user must have access to the specified thread. Results are returned in a single page; there is no cursor-based pagination for this endpoint.
Arguments:
- thread: Thread ID (
thr_...). Must be accessible to the authenticated user.
Returns:
Successful response
1154 async def mark_read(self, thread: str, input: ThreadMarkReadInput) -> None: 1155 """ 1156 Mark a thread as read 1157 Records that a user has read up to a specific message in the thread. Unread 1158 indicators and badge counts are cleared up to the specified message. 1159 You must supply exactly one of `last_read_message` or `use_latest_message`. 1160 Omitting both returns 400. If `use_latest_message` is `true` and the thread 1161 has no messages, the request succeeds silently with no state change. 1162 For server-to-server (S2S) requests where no user identity is present in the 1163 token, the `user` param is required to identify whose read state to update. 1164 1165 Args: 1166 thread: Thread ID (`thr_...`). The thread to mark as read. 1167 input: Request body. 1168 input.last_read_message: Message ID (`msg_...`) to record as the last read message. Mutually exclusive with `use_latest_message`. 1169 input.use_latest_message: When `true`, marks the thread as read up to the latest message. Mutually exclusive with `last_read_message`. 1170 input.user: User ID (`usr_...`) whose read state to update. Required for S2S requests; ignored when an authenticated user is present in the token. 1171 1172 Returns: 1173 Empty response on success. 1174 """ 1175 await self._http.request(f"/api/v1/threads/{thread}/mark_read", method="POST", body=input)
Mark a thread as read
Records that a user has read up to a specific message in the thread. Unread
indicators and badge counts are cleared up to the specified message.
You must supply exactly one of last_read_message or use_latest_message.
Omitting both returns 400. If use_latest_message is true and the thread
has no messages, the request succeeds silently with no state change.
For server-to-server (S2S) requests where no user identity is present in the
token, the user param is required to identify whose read state to update.
Arguments:
- thread: Thread ID (
thr_...). The thread to mark as read. - input: Request body.
- input.last_read_message: Message ID (
msg_...) to record as the last read message. Mutually exclusive withuse_latest_message. - input.use_latest_message: When
true, marks the thread as read up to the latest message. Mutually exclusive withlast_read_message. - input.user: User ID (
usr_...) whose read state to update. Required for S2S requests; ignored when an authenticated user is present in the token.
Returns:
Empty response on success.
1177 async def messages( 1178 self, 1179 thread: str, 1180 *, 1181 before_cursor: str | None = None, 1182 after_cursor: str | None = None, 1183 metadata: dict[str, Any] | None = None, 1184 limit: int | None = None, 1185 anchor: str | None = None, 1186 direction: Literal["before", "after", "around"] | None = None, 1187 before_limit: int | None = None, 1188 after_limit: int | None = None, 1189 include_anchor: bool | None = None, 1190 anchor_agent_mode: Literal["cli", "embedded"] | None = None, 1191 anchor_agent: str | None = None, 1192 include_reply_counts: bool | None = None, 1193 ) -> ThreadMessagesResponse: 1194 """ 1195 List messages in a thread 1196 Returns a cursor-paginated list of messages belonging to the specified thread, 1197 ordered from oldest to newest. Supply `before_cursor`, `after_cursor`, or both 1198 to page through or bound the result set; omit both to receive the most recent page. 1199 Supply `anchor` and `direction` to fetch a window before, after, or around a 1200 specific message. Use `anchor=last_matching&anchor_agent_mode=embedded` to 1201 resolve the anchor from the latest embedded-agent message, and add 1202 `anchor_agent` to scope that resolution to a single sender agent. 1203 Supply `metadata` as a JSON-encoded structured expression to filter message 1204 metadata before cursor pagination or anchored window limits are applied. 1205 The authenticated user must have access to the thread's owner (workspace or user). 1206 A 403 is returned if the thread exists but is not accessible to the caller; a 404 1207 is returned if the thread does not exist or is not visible to the authenticated user. 1208 Pass `include_reply_counts: true` to annotate each message with the number of 1209 threaded replies it has received. This adds a small amount of latency and should 1210 be omitted when reply counts are not needed. 1211 1212 Args: 1213 thread: Thread ID (`thr_...`). The authenticated user must have access to this thread. 1214 before_cursor: Opaque cursor returned in a previous response's `before_cursor` field. When provided, returns messages immediately before that position. May be combined with `after_cursor` to bound a range. 1215 after_cursor: Opaque cursor returned in a previous response's `after_cursor` field. When provided, returns messages immediately after that position. May be combined with `before_cursor` to bound a range. 1216 metadata: Structured metadata filter expression. Only messages whose `metadata` object satisfies the expression are returned. The filter is applied before cursor pagination and anchored window limits. 1217 limit: Maximum number of messages to return per page. Defaults to 20; maximum is 100. 1218 anchor: Message ID (`msg_...`) to use as a window anchor, or `last_matching` to resolve the anchor from the latest message matching the anchor filters. Cannot be combined with `before_cursor` or `after_cursor`. 1219 direction: Window direction relative to `anchor`. `before` returns older messages, `after` returns newer messages, and `around` returns messages on both sides. Defaults to `after` when `anchor` is supplied. `direction=around` cannot be combined with an explicit `limit`; use `before_limit` and `after_limit`. 1220 before_limit: For `direction=around`, maximum number of messages older than the anchor. Defaults to 20; maximum is 100. 1221 after_limit: For `direction=around`, maximum number of messages newer than the anchor. Defaults to 20; maximum is 100. 1222 include_anchor: Whether to include the anchor message in a window response. Defaults to `true` for `direction=around`; ignored for ordinary cursor pagination and one-sided windows. 1223 anchor_agent_mode: When `anchor=last_matching`, resolve the anchor from the latest message with this local agent execution mode. 1224 anchor_agent: When `anchor=last_matching`, scope the anchor resolution to messages sent by this agent (`agi_...`). Combine with `anchor_agent_mode` to resolve the latest message from a specific agent in a given mode. 1225 include_reply_counts: When `true`, each message in the response is annotated with its threaded reply count. Defaults to `false`. Adds latency; omit when reply counts are not needed. 1226 1227 Returns: 1228 Successful response 1229 """ 1230 query: dict[str, object] = {} 1231 if before_cursor is not None: 1232 query["before_cursor"] = before_cursor 1233 if after_cursor is not None: 1234 query["after_cursor"] = after_cursor 1235 if metadata is not None: 1236 query["metadata"] = metadata 1237 if limit is not None: 1238 query["limit"] = limit 1239 if anchor is not None: 1240 query["anchor"] = anchor 1241 if direction is not None: 1242 query["direction"] = direction 1243 if before_limit is not None: 1244 query["before_limit"] = before_limit 1245 if after_limit is not None: 1246 query["after_limit"] = after_limit 1247 if include_anchor is not None: 1248 query["include_anchor"] = include_anchor 1249 if anchor_agent_mode is not None: 1250 query["anchor_agent_mode"] = anchor_agent_mode 1251 if anchor_agent is not None: 1252 query["anchor_agent"] = anchor_agent 1253 if include_reply_counts is not None: 1254 query["include_reply_counts"] = include_reply_counts 1255 return await self._http.request( 1256 f"/api/v1/threads/{thread}/messages", 1257 query=query, 1258 response_type=ThreadMessagesResponse, 1259 )
List messages in a thread
Returns a cursor-paginated list of messages belonging to the specified thread,
ordered from oldest to newest. Supply before_cursor, after_cursor, or both
to page through or bound the result set; omit both to receive the most recent page.
Supply anchor and direction to fetch a window before, after, or around a
specific message. Use anchor=last_matching&anchor_agent_mode=embedded to
resolve the anchor from the latest embedded-agent message, and add
anchor_agent to scope that resolution to a single sender agent.
Supply metadata as a JSON-encoded structured expression to filter message
metadata before cursor pagination or anchored window limits are applied.
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.
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.
Arguments:
- thread: Thread ID (
thr_...). The authenticated user must have access to this thread. - before_cursor: Opaque cursor returned in a previous response's
before_cursorfield. When provided, returns messages immediately before that position. May be combined withafter_cursorto bound a range. - after_cursor: Opaque cursor returned in a previous response's
after_cursorfield. When provided, returns messages immediately after that position. May be combined withbefore_cursorto bound a range. - metadata: Structured metadata filter expression. Only messages whose
metadataobject satisfies the expression are returned. The filter is applied before cursor pagination and anchored window limits. - limit: Maximum number of messages to return per page. Defaults to 20; maximum is 100.
- anchor: Message ID (
msg_...) to use as a window anchor, orlast_matchingto resolve the anchor from the latest message matching the anchor filters. Cannot be combined withbefore_cursororafter_cursor. - direction: Window direction relative to
anchor.beforereturns older messages,afterreturns newer messages, andaroundreturns messages on both sides. Defaults toafterwhenanchoris supplied.direction=aroundcannot be combined with an explicitlimit; usebefore_limitandafter_limit. - before_limit: For
direction=around, maximum number of messages older than the anchor. Defaults to 20; maximum is 100. - after_limit: For
direction=around, maximum number of messages newer than the anchor. Defaults to 20; maximum is 100. - include_anchor: Whether to include the anchor message in a window response. Defaults to
truefordirection=around; ignored for ordinary cursor pagination and one-sided windows. - anchor_agent_mode: When
anchor=last_matching, resolve the anchor from the latest message with this local agent execution mode. - anchor_agent: When
anchor=last_matching, scope the anchor resolution to messages sent by this agent (agi_...). Combine withanchor_agent_modeto resolve the latest message from a specific agent in a given mode. - include_reply_counts: When
true, each message in the response is annotated with its threaded reply count. Defaults tofalse. Adds latency; omit when reply counts are not needed.
Returns:
Successful response
1261 async def picture(self, thread: str, input: ThreadPictureInput) -> Thread: 1262 """ 1263 Update a thread's profile picture 1264 Uploads a new profile picture for the specified thread and returns the updated 1265 thread object. The image must be supplied as a base64-encoded string with its 1266 MIME type. 1267 The authenticated user must own the thread or be a team owner of the workspace 1268 the thread belongs to. Supplying invalid base64 data returns 422. 1269 1270 Args: 1271 thread: Thread ID (`thr_...`). The authenticated user must have permission to update this thread. 1272 input: Request body. 1273 input.picture: Profile picture payload. Must include the base64-encoded image data and its MIME type. 1274 1275 Returns: 1276 The thread object after the profile picture has been updated. 1277 """ 1278 return await self._http.request( 1279 f"/api/v1/threads/{thread}/picture", 1280 method="PUT", 1281 body=input, 1282 response_type=Thread, 1283 )
Update a thread's profile picture Uploads a new profile picture for the specified thread and returns the updated thread object. The image must be supplied as a base64-encoded string with its MIME type. The authenticated user must own the thread or be a team owner of the workspace the thread belongs to. Supplying invalid base64 data returns 422.
Arguments:
- thread: Thread ID (
thr_...). The authenticated user must have permission to update this thread. - input: Request body.
- input.picture: Profile picture payload. Must include the base64-encoded image data and its MIME type.
Returns:
The thread object after the profile picture has been updated.
1285 async def read_status(self, thread: str, *, user: str | None = None) -> ThreadReadStatus: 1286 """ 1287 Retrieve a thread's read status 1288 Returns the read status of a thread for the specified user, including the ID 1289 of the last message they have read and the number of unread messages remaining. 1290 For user-authenticated requests, the status is always returned for the 1291 authenticated user and the `user` parameter is ignored. For server-to-server 1292 (S2S) requests, the `user` parameter is required and must be a valid user ID. 1293 Returns 404 if the thread does not exist or the caller does not have access 1294 to it. 1295 1296 Args: 1297 thread: Thread ID (`thr_...`). Must be accessible to the authenticated user or, for S2S requests, to the specified user. 1298 user: User ID (`usr_...`) whose read status to retrieve. Required for S2S requests; ignored for user-authenticated requests, which always return the status for the authenticated user. 1299 1300 Returns: 1301 The read status record for the requested thread and user. 1302 """ 1303 query: dict[str, object] = {} 1304 if user is not None: 1305 query["user"] = user 1306 return await self._http.request( 1307 f"/api/v1/threads/{thread}/read_status", 1308 query=query, 1309 response_type=ThreadReadStatus, 1310 )
Retrieve a thread's read status
Returns the read status of a thread for the specified user, including the ID
of the last message they have read and the number of unread messages remaining.
For user-authenticated requests, the status is always returned for the
authenticated user and the user parameter is ignored. For server-to-server
(S2S) requests, the user parameter is required and must be a valid user ID.
Returns 404 if the thread does not exist or the caller does not have access
to it.
Arguments:
- thread: Thread ID (
thr_...). Must be accessible to the authenticated user or, for S2S requests, to the specified user. - user: User ID (
usr_...) whose read status to retrieve. Required for S2S requests; ignored for user-authenticated requests, which always return the status for the authenticated user.
Returns:
The read status record for the requested thread and user.
1312 async def search( 1313 self, 1314 thread: str, 1315 q: str, 1316 *, 1317 app: str | None = None, 1318 limit: int | None = None, 1319 mode: Literal["text", "embedding", "hybrid"] | None = None, 1320 before_cursor: str | None = None, 1321 after_cursor: str | None = None, 1322 ) -> ThreadSearchResponse: 1323 """ 1324 Search messages in a thread 1325 Searches canonical message content in the specified thread. `"text"` mode 1326 performs the existing case-insensitive substring search, `"embedding"` ranks 1327 stored message embeddings by cosine similarity, and `"hybrid"` combines the 1328 text and embedding rankings with Reciprocal Rank Fusion (RRF). Only messages 1329 visible to the authenticated caller are considered. 1330 Results are intentionally lean: each row contains only a bounded content 1331 snippet, sender identity, and timestamp. Attachments, reactions, ACLs, and 1332 metadata are neither hydrated nor serialized. At most 20 results are 1333 returned. Text results support chronological cursor pagination. Embedding and 1334 hybrid results are relevance-ranked single pages and return null cursors. 1335 1336 Args: 1337 thread: Thread ID (`thr_...`). Must be visible to the authenticated caller. 1338 app: App ID (`app_...`). Required by the protected developer mount and omitted from the public mount. 1339 q: Text or semantic search query. Must contain 3 to 200 characters after trimming. 1340 limit: Maximum number of results. Defaults to 20 and is capped at 20. 1341 mode: Search algorithm: `text` for substring matching, `embedding` for cosine similarity, or `hybrid` for RRF over both rankings. 1342 before_cursor: Text mode only. Opaque cursor returned by a previous page; fetches older matches. 1343 after_cursor: Text mode only. Opaque cursor returned by a previous page; fetches newer matches. 1344 1345 Returns: 1346 Successful response 1347 """ 1348 query: dict[str, object] = {} 1349 if app is not None: 1350 query["app"] = app 1351 query["q"] = q 1352 if limit is not None: 1353 query["limit"] = limit 1354 if mode is not None: 1355 query["mode"] = mode 1356 if before_cursor is not None: 1357 query["before_cursor"] = before_cursor 1358 if after_cursor is not None: 1359 query["after_cursor"] = after_cursor 1360 return await self._http.request( 1361 f"/api/v1/threads/{thread}/search", 1362 query=query, 1363 response_type=ThreadSearchResponse, 1364 )
Search messages in a thread
Searches canonical message content in the specified thread. "text" mode
performs the existing case-insensitive substring search, "embedding" ranks
stored message embeddings by cosine similarity, and "hybrid" combines the
text and embedding rankings with Reciprocal Rank Fusion (RRF). Only messages
visible to the authenticated caller are considered.
Results are intentionally lean: each row contains only a bounded content
snippet, sender identity, and timestamp. Attachments, reactions, ACLs, and
metadata are neither hydrated nor serialized. At most 20 results are
returned. Text results support chronological cursor pagination. Embedding and
hybrid results are relevance-ranked single pages and return null cursors.
Arguments:
- thread: Thread ID (
thr_...). Must be visible to the authenticated caller. - app: App ID (
app_...). Required by the protected developer mount and omitted from the public mount. - q: Text or semantic search query. Must contain 3 to 200 characters after trimming.
- limit: Maximum number of results. Defaults to 20 and is capped at 20.
- mode: Search algorithm:
textfor substring matching,embeddingfor cosine similarity, orhybridfor RRF over both rankings. - before_cursor: Text mode only. Opaque cursor returned by a previous page; fetches older matches.
- after_cursor: Text mode only. Opaque cursor returned by a previous page; fetches newer matches.
Returns:
Successful response
1366 async def trajectories( 1367 self, 1368 thread: str, 1369 *, 1370 before_cursor: str | None = None, 1371 after_cursor: str | None = None, 1372 limit: int | None = None, 1373 message: str | None = None, 1374 ) -> ThreadTrajectoriesResponse: 1375 """ 1376 List trajectories for a thread 1377 Returns a cursor-paginated list of thread message trajectories associated with the 1378 specified thread. Each trajectory links a user message and its agent response to the 1379 underlying AI trajectory record that captured the model's reasoning steps. 1380 The authenticated user must own the thread or be a member of the workspace it belongs 1381 to. Results are returned in reverse chronological order by default. Use `before_cursor` 1382 and `after_cursor` to navigate pages; provide at most one cursor per request. 1383 Optionally filter results to trajectories produced in response to a specific message 1384 by supplying the `message` parameter. When no trajectories match the query, `data` 1385 is an empty array and both cursor fields are `null`. A cursor that cannot be decoded 1386 returns a 400 `invalid_cursor` error. 1387 1388 Args: 1389 thread: Thread ID (`thr_...`). The authenticated user must own this thread or belong to its workspace. 1390 before_cursor: Opaque cursor from a previous response's `before_cursor` field. Returns the page of results preceding that cursor position. 1391 after_cursor: Opaque cursor from a previous response's `after_cursor` field. Returns the page of results following that cursor position. 1392 limit: Maximum number of trajectories to return per page. Defaults to 20; maximum is 100. 1393 message: Message ID (`msg_...`). When provided, limits results to trajectories associated with this specific message. 1394 1395 Returns: 1396 Successful response 1397 """ 1398 query: dict[str, object] = {} 1399 if before_cursor is not None: 1400 query["before_cursor"] = before_cursor 1401 if after_cursor is not None: 1402 query["after_cursor"] = after_cursor 1403 if limit is not None: 1404 query["limit"] = limit 1405 if message is not None: 1406 query["message"] = message 1407 return await self._http.request( 1408 f"/api/v1/threads/{thread}/trajectories", 1409 query=query, 1410 response_type=ThreadTrajectoriesResponse, 1411 )
List trajectories for a thread
Returns a cursor-paginated list of thread message trajectories associated with the
specified thread. Each trajectory links a user message and its agent response to the
underlying AI trajectory record that captured the model's reasoning steps.
The authenticated user must own the thread or be a member of the workspace it belongs
to. Results are returned in reverse chronological order by default. Use before_cursor
and after_cursor to navigate pages; provide at most one cursor per request.
Optionally filter results to trajectories produced in response to a specific message
by supplying the message parameter. When no trajectories match the query, data
is an empty array and both cursor fields are null. A cursor that cannot be decoded
returns a 400 invalid_cursor error.
Arguments:
- thread: Thread ID (
thr_...). The authenticated user must own this thread or belong to its workspace. - before_cursor: Opaque cursor from a previous response's
before_cursorfield. Returns the page of results preceding that cursor position. - after_cursor: Opaque cursor from a previous response's
after_cursorfield. Returns the page of results following that cursor position. - limit: Maximum number of trajectories to return per page. Defaults to 20; maximum is 100.
- message: Message ID (
msg_...). When provided, limits results to trajectories associated with this specific message.
Returns:
Successful response
1414class ThreadMemberResource: 1415 def __init__(self, http: SyncHttpClient): 1416 self._http = http 1417 1418 def remove(self, thread: str) -> None: 1419 """ 1420 Remove a member from a thread 1421 Removes a user or agent from the explicit roster of a private or restricted 1422 thread. Team-visible threads use implicit membership and reject individual 1423 removals. A member may remove themself; removing someone else requires 1424 permission to modify the thread. A successful removal returns HTTP 204 with 1425 no response body. 1426 Supply either `user` or `agent` depending on the value of `type`. Returns 404 1427 if the thread or the membership record does not exist. 1428 1429 Args: 1430 thread: Thread ID (`thr_...`) identifying the thread to remove the member from. 1431 1432 Returns: 1433 Empty response body. HTTP 204 on success. 1434 """ 1435 self._http.request(f"/api/v1/threads/{thread}/members", method="DELETE") 1436 1437 def list(self, thread: str) -> ThreadMemberListResponse: 1438 """ 1439 List members of a thread 1440 Returns all current user and agent members. Private and restricted threads 1441 return their explicit roster; team-visible threads return the owning team's 1442 implicit roster. The authenticated viewer must be able to see the thread. 1443 Results are returned as a flat array in the `data` field. The list is not 1444 paginated all members are returned in a single response. 1445 1446 Args: 1447 thread: Thread ID (`thr_...`) identifying the thread to remove the member from. 1448 1449 Returns: 1450 Successful response 1451 """ 1452 return self._http.request( 1453 f"/api/v1/threads/{thread}/members", 1454 response_type=ThreadMemberListResponse, 1455 ) 1456 1457 def create(self, thread: str, input: ThreadMemberCreateInput) -> ChatMember: 1458 """ 1459 Add a member to a thread 1460 Adds a user or agent to the explicit roster of a private or restricted 1461 thread. Team-visible threads use the owning team's implicit roster and reject 1462 explicit additions. On restricted threads, a team member may add themself; 1463 adding anyone else requires permission to modify the thread. 1464 Supply either `user` or `agent` depending on the value of `type`. Targets 1465 must be visible to the caller and, for an ordinary team-owned thread, must 1466 belong to the owning team. On success the membership record is returned with 1467 HTTP 201; repeated agent additions are idempotent. 1468 1469 Args: 1470 thread: Thread ID (`thr_...`) identifying the thread to remove the member from. 1471 input: Request body. 1472 input.agent: Agent ID of the principal to add. Required when `type` is `"agent"`. 1473 input.membership_type: Role granted to the new member. One of `"owner"` or `"member"`. Defaults to `"member"`. 1474 input.type: Kind of principal being added. Must be `"user"` or `"agent"`. 1475 input.user: User ID of the principal to add. Required when `type` is `"user"`. 1476 1477 Returns: 1478 The user or agent membership that was added to the thread. 1479 """ 1480 return self._http.request( 1481 f"/api/v1/threads/{thread}/members", 1482 method="POST", 1483 body=input, 1484 response_type=ChatMember, 1485 )
1418 def remove(self, thread: str) -> None: 1419 """ 1420 Remove a member from a thread 1421 Removes a user or agent from the explicit roster of a private or restricted 1422 thread. Team-visible threads use implicit membership and reject individual 1423 removals. A member may remove themself; removing someone else requires 1424 permission to modify the thread. A successful removal returns HTTP 204 with 1425 no response body. 1426 Supply either `user` or `agent` depending on the value of `type`. Returns 404 1427 if the thread or the membership record does not exist. 1428 1429 Args: 1430 thread: Thread ID (`thr_...`) identifying the thread to remove the member from. 1431 1432 Returns: 1433 Empty response body. HTTP 204 on success. 1434 """ 1435 self._http.request(f"/api/v1/threads/{thread}/members", method="DELETE")
Remove a member from a thread
Removes a user or agent from the explicit roster of a private or restricted
thread. Team-visible threads use implicit membership and reject individual
removals. A member may remove themself; removing someone else requires
permission to modify the thread. A successful removal returns HTTP 204 with
no response body.
Supply either user or agent depending on the value of type. Returns 404
if the thread or the membership record does not exist.
Arguments:
- thread: Thread ID (
thr_...) identifying the thread to remove the member from.
Returns:
Empty response body. HTTP 204 on success.
1437 def list(self, thread: str) -> ThreadMemberListResponse: 1438 """ 1439 List members of a thread 1440 Returns all current user and agent members. Private and restricted threads 1441 return their explicit roster; team-visible threads return the owning team's 1442 implicit roster. The authenticated viewer must be able to see the thread. 1443 Results are returned as a flat array in the `data` field. The list is not 1444 paginated all members are returned in a single response. 1445 1446 Args: 1447 thread: Thread ID (`thr_...`) identifying the thread to remove the member from. 1448 1449 Returns: 1450 Successful response 1451 """ 1452 return self._http.request( 1453 f"/api/v1/threads/{thread}/members", 1454 response_type=ThreadMemberListResponse, 1455 )
List members of a thread
Returns all current user and agent members. Private and restricted threads
return their explicit roster; team-visible threads return the owning team's
implicit roster. The authenticated viewer must be able to see the thread.
Results are returned as a flat array in the data field. The list is not
paginated all members are returned in a single response.
Arguments:
- thread: Thread ID (
thr_...) identifying the thread to remove the member from.
Returns:
Successful response
1457 def create(self, thread: str, input: ThreadMemberCreateInput) -> ChatMember: 1458 """ 1459 Add a member to a thread 1460 Adds a user or agent to the explicit roster of a private or restricted 1461 thread. Team-visible threads use the owning team's implicit roster and reject 1462 explicit additions. On restricted threads, a team member may add themself; 1463 adding anyone else requires permission to modify the thread. 1464 Supply either `user` or `agent` depending on the value of `type`. Targets 1465 must be visible to the caller and, for an ordinary team-owned thread, must 1466 belong to the owning team. On success the membership record is returned with 1467 HTTP 201; repeated agent additions are idempotent. 1468 1469 Args: 1470 thread: Thread ID (`thr_...`) identifying the thread to remove the member from. 1471 input: Request body. 1472 input.agent: Agent ID of the principal to add. Required when `type` is `"agent"`. 1473 input.membership_type: Role granted to the new member. One of `"owner"` or `"member"`. Defaults to `"member"`. 1474 input.type: Kind of principal being added. Must be `"user"` or `"agent"`. 1475 input.user: User ID of the principal to add. Required when `type` is `"user"`. 1476 1477 Returns: 1478 The user or agent membership that was added to the thread. 1479 """ 1480 return self._http.request( 1481 f"/api/v1/threads/{thread}/members", 1482 method="POST", 1483 body=input, 1484 response_type=ChatMember, 1485 )
Add a member to a thread
Adds a user or agent to the explicit roster of a private or restricted
thread. Team-visible threads use the owning team's implicit roster and reject
explicit additions. On restricted threads, a team member may add themself;
adding anyone else requires permission to modify the thread.
Supply either user or agent depending on the value of type. Targets
must be visible to the caller and, for an ordinary team-owned thread, must
belong to the owning team. On success the membership record is returned with
HTTP 201; repeated agent additions are idempotent.
Arguments:
- thread: Thread ID (
thr_...) identifying the thread to remove the member from. - input: Request body.
- input.agent: Agent ID of the principal to add. Required when
typeis"agent". - input.membership_type: Role granted to the new member. One of
"owner"or"member". Defaults to"member". - input.type: Kind of principal being added. Must be
"user"or"agent". - input.user: User ID of the principal to add. Required when
typeis"user".
Returns:
The user or agent membership that was added to the thread.
1488class SettingResource: 1489 def __init__(self, http: SyncHttpClient): 1490 self._http = http 1491 1492 def list(self, thread: str) -> SettingListResponse: 1493 """ 1494 Retrieve thread settings 1495 Returns the current settings for the specified thread. Settings control 1496 per-thread behavior such as whether the AI agent is enabled. 1497 The authenticated user must own the thread or be a member of its workspace. 1498 If settings have never been explicitly configured, defaults are returned 1499 (for example, `agent_enabled` defaults to `true`). 1500 1501 Args: 1502 thread: Thread ID (`thr_...`). Must belong to the authenticated user's workspace. 1503 1504 Returns: 1505 Successful response 1506 """ 1507 return self._http.request( 1508 f"/api/v1/threads/{thread}/settings", 1509 response_type=SettingListResponse, 1510 ) 1511 1512 def replace(self, thread: str, input: SettingReplaceInput) -> ThreadSettings: 1513 """ 1514 Update thread settings 1515 Updates the settings for the specified thread. Only fields included in 1516 the `settings` map are modified; omitted fields retain their current values. 1517 The authenticated user must own the thread or be a member of its workspace. 1518 Returns the full settings object reflecting the state after the update. 1519 Validation errors are returned as `422 Unprocessable Entity`. 1520 1521 Args: 1522 thread: Thread ID (`thr_...`). Must belong to the authenticated user's workspace. 1523 input: Request body. 1524 input.settings: Map of settings fields to update. Include only the keys you want to change. 1525 1526 Returns: 1527 The thread settings object after the update has been applied. 1528 """ 1529 return self._http.request( 1530 f"/api/v1/threads/{thread}/settings", 1531 method="PUT", 1532 body=input, 1533 response_type=ThreadSettings, 1534 )
1492 def list(self, thread: str) -> SettingListResponse: 1493 """ 1494 Retrieve thread settings 1495 Returns the current settings for the specified thread. Settings control 1496 per-thread behavior such as whether the AI agent is enabled. 1497 The authenticated user must own the thread or be a member of its workspace. 1498 If settings have never been explicitly configured, defaults are returned 1499 (for example, `agent_enabled` defaults to `true`). 1500 1501 Args: 1502 thread: Thread ID (`thr_...`). Must belong to the authenticated user's workspace. 1503 1504 Returns: 1505 Successful response 1506 """ 1507 return self._http.request( 1508 f"/api/v1/threads/{thread}/settings", 1509 response_type=SettingListResponse, 1510 )
Retrieve thread settings
Returns the current settings for the specified thread. Settings control
per-thread behavior such as whether the AI agent is enabled.
The authenticated user must own the thread or be a member of its workspace.
If settings have never been explicitly configured, defaults are returned
(for example, agent_enabled defaults to true).
Arguments:
- thread: Thread ID (
thr_...). Must belong to the authenticated user's workspace.
Returns:
Successful response
1512 def replace(self, thread: str, input: SettingReplaceInput) -> ThreadSettings: 1513 """ 1514 Update thread settings 1515 Updates the settings for the specified thread. Only fields included in 1516 the `settings` map are modified; omitted fields retain their current values. 1517 The authenticated user must own the thread or be a member of its workspace. 1518 Returns the full settings object reflecting the state after the update. 1519 Validation errors are returned as `422 Unprocessable Entity`. 1520 1521 Args: 1522 thread: Thread ID (`thr_...`). Must belong to the authenticated user's workspace. 1523 input: Request body. 1524 input.settings: Map of settings fields to update. Include only the keys you want to change. 1525 1526 Returns: 1527 The thread settings object after the update has been applied. 1528 """ 1529 return self._http.request( 1530 f"/api/v1/threads/{thread}/settings", 1531 method="PUT", 1532 body=input, 1533 response_type=ThreadSettings, 1534 )
Update thread settings
Updates the settings for the specified thread. Only fields included in
the settings map are modified; omitted fields retain their current values.
The authenticated user must own the thread or be a member of its workspace.
Returns the full settings object reflecting the state after the update.
Validation errors are returned as 422 Unprocessable Entity.
Arguments:
- thread: Thread ID (
thr_...). Must belong to the authenticated user's workspace. - input: Request body.
- input.settings: Map of settings fields to update. Include only the keys you want to change.
Returns:
The thread settings object after the update has been applied.
1537class TagResource: 1538 def __init__(self, http: SyncHttpClient): 1539 self._http = http 1540 1541 def remove(self, thread: str) -> Thread: 1542 """ 1543 Remove tags from a thread 1544 Removes one or more status tags from the thread and returns the updated 1545 thread. Removing a tag the thread does not have is a no-op. 1546 Any participant of the thread a human member or an agent member may edit 1547 tags. Supply the tags to remove as repeated query parameters, e.g. 1548 `?tags[]=blocked&tags[]=needs-review`. 1549 1550 Args: 1551 thread: Thread ID (`thr_...`) to untag. 1552 1553 Returns: 1554 The thread object after the tags were removed. 1555 """ 1556 return self._http.request( 1557 f"/api/v1/threads/{thread}/tags", 1558 method="DELETE", 1559 response_type=Thread, 1560 ) 1561 1562 def create(self, thread: str, input: TagCreateInput) -> Thread: 1563 """ 1564 Add tags to a thread 1565 Adds one or more status tags to the thread and returns the updated thread. 1566 Any participant of the thread a human member or an agent member may edit 1567 tags; this is broader than the owner/admin permission required to update other 1568 thread fields. Adding a tag the thread already has is a no-op. Tags are 1569 normalized (trimmed and lowercased) and may contain only lowercase letters, 1570 numbers, hyphens, and underscores. 1571 1572 Args: 1573 thread: Thread ID (`thr_...`) to untag. 1574 input: Request body. 1575 input.tags: Tags to add to the thread. 1576 1577 Returns: 1578 The thread object after the tags were added. 1579 """ 1580 return self._http.request( 1581 f"/api/v1/threads/{thread}/tags", 1582 method="POST", 1583 body=input, 1584 response_type=Thread, 1585 ) 1586 1587 def replace(self, thread: str, input: TagReplaceInput) -> Thread: 1588 """ 1589 Replace a thread's tags 1590 Replaces the thread's entire set of status tags with the provided list and 1591 returns the updated thread. Passing an empty array clears all tags. 1592 Any participant of the thread a human member or an agent member may edit 1593 tags. Tags are normalized (trimmed and lowercased) and may contain only 1594 lowercase letters, numbers, hyphens, and underscores. 1595 1596 Args: 1597 thread: Thread ID (`thr_...`) to untag. 1598 input: Request body. 1599 input.tags: The complete set of tags for the thread. An empty array clears all tags. 1600 1601 Returns: 1602 The thread object after its tags were replaced. 1603 """ 1604 return self._http.request( 1605 f"/api/v1/threads/{thread}/tags", 1606 method="PUT", 1607 body=input, 1608 response_type=Thread, 1609 )
1541 def remove(self, thread: str) -> Thread: 1542 """ 1543 Remove tags from a thread 1544 Removes one or more status tags from the thread and returns the updated 1545 thread. Removing a tag the thread does not have is a no-op. 1546 Any participant of the thread a human member or an agent member may edit 1547 tags. Supply the tags to remove as repeated query parameters, e.g. 1548 `?tags[]=blocked&tags[]=needs-review`. 1549 1550 Args: 1551 thread: Thread ID (`thr_...`) to untag. 1552 1553 Returns: 1554 The thread object after the tags were removed. 1555 """ 1556 return self._http.request( 1557 f"/api/v1/threads/{thread}/tags", 1558 method="DELETE", 1559 response_type=Thread, 1560 )
Remove tags from a thread
Removes one or more status tags from the thread and returns the updated
thread. Removing a tag the thread does not have is a no-op.
Any participant of the thread a human member or an agent member may edit
tags. Supply the tags to remove as repeated query parameters, e.g.
?tags[]=blocked&tags[]=needs-review.
Arguments:
- thread: Thread ID (
thr_...) to untag.
Returns:
The thread object after the tags were removed.
1562 def create(self, thread: str, input: TagCreateInput) -> Thread: 1563 """ 1564 Add tags to a thread 1565 Adds one or more status tags to the thread and returns the updated thread. 1566 Any participant of the thread a human member or an agent member may edit 1567 tags; this is broader than the owner/admin permission required to update other 1568 thread fields. Adding a tag the thread already has is a no-op. Tags are 1569 normalized (trimmed and lowercased) and may contain only lowercase letters, 1570 numbers, hyphens, and underscores. 1571 1572 Args: 1573 thread: Thread ID (`thr_...`) to untag. 1574 input: Request body. 1575 input.tags: Tags to add to the thread. 1576 1577 Returns: 1578 The thread object after the tags were added. 1579 """ 1580 return self._http.request( 1581 f"/api/v1/threads/{thread}/tags", 1582 method="POST", 1583 body=input, 1584 response_type=Thread, 1585 )
Add tags to a thread Adds one or more status tags to the thread and returns the updated thread. Any participant of the thread a human member or an agent member may edit tags; this is broader than the owner/admin permission required to update other thread fields. Adding a tag the thread already has is a no-op. Tags are normalized (trimmed and lowercased) and may contain only lowercase letters, numbers, hyphens, and underscores.
Arguments:
- thread: Thread ID (
thr_...) to untag. - input: Request body.
- input.tags: Tags to add to the thread.
Returns:
The thread object after the tags were added.
1587 def replace(self, thread: str, input: TagReplaceInput) -> Thread: 1588 """ 1589 Replace a thread's tags 1590 Replaces the thread's entire set of status tags with the provided list and 1591 returns the updated thread. Passing an empty array clears all tags. 1592 Any participant of the thread a human member or an agent member may edit 1593 tags. Tags are normalized (trimmed and lowercased) and may contain only 1594 lowercase letters, numbers, hyphens, and underscores. 1595 1596 Args: 1597 thread: Thread ID (`thr_...`) to untag. 1598 input: Request body. 1599 input.tags: The complete set of tags for the thread. An empty array clears all tags. 1600 1601 Returns: 1602 The thread object after its tags were replaced. 1603 """ 1604 return self._http.request( 1605 f"/api/v1/threads/{thread}/tags", 1606 method="PUT", 1607 body=input, 1608 response_type=Thread, 1609 )
Replace a thread's tags Replaces the thread's entire set of status tags with the provided list and returns the updated thread. Passing an empty array clears all tags. Any participant of the thread a human member or an agent member may edit tags. Tags are normalized (trimmed and lowercased) and may contain only lowercase letters, numbers, hyphens, and underscores.
Arguments:
- thread: Thread ID (
thr_...) to untag. - input: Request body.
- input.tags: The complete set of tags for the thread. An empty array clears all tags.
Returns:
The thread object after its tags were replaced.
1612class ThreadResource: 1613 def __init__(self, http: SyncHttpClient): 1614 self._http = http 1615 self.members = ThreadMemberResource(http) 1616 self.settings = SettingResource(http) 1617 self.tags = TagResource(http) 1618 1619 def delete(self, thread: str) -> None: 1620 """ 1621 Delete a thread 1622 Permanently deletes a thread and all of its messages and artifacts. This action 1623 cannot be undone. 1624 The authenticated user must own the thread or be an owner of the team the thread 1625 belongs to. Attempting to delete a thread owned by another user or team returns 403. 1626 1627 Args: 1628 thread: Thread ID (`thr_...`). The authenticated user must own this thread. 1629 1630 Returns: 1631 Empty response on successful deletion. 1632 """ 1633 self._http.request(f"/api/v1/threads/{thread}", method="DELETE") 1634 1635 def get(self, thread: str) -> Thread: 1636 """ 1637 Retrieve a thread 1638 Returns the full thread record for the given thread ID. The authenticated user 1639 must own the thread or be a member of the workspace it belongs to. 1640 Use this endpoint to fetch the current state of a single thread, including its 1641 title, description, and metadata. To list many threads, use the list endpoint 1642 with cursor-based pagination. 1643 1644 Args: 1645 thread: Thread ID (`thr_...`). The authenticated user must have access to this thread. 1646 1647 Returns: 1648 The requested thread object. 1649 """ 1650 return self._http.request(f"/api/v1/threads/{thread}", response_type=Thread) 1651 1652 def replace(self, thread: str, input: ThreadReplaceInput) -> Thread: 1653 """ 1654 Update a thread 1655 Updates one or more mutable properties of the specified thread and returns 1656 the full thread object with the applied changes. Only the fields you provide 1657 are modified; omitted fields retain their current values. 1658 If `profile_picture` is supplied, the image is uploaded before the other 1659 fields are saved, after all ordinary thread fields have passed validation. 1660 Supplying invalid base64 picture data returns 422 and no other fields are 1661 updated. 1662 Visibility can only widen: `private` may become `restricted` or `team`, and 1663 `restricted` may become `team`. The authenticated viewer must have 1664 permission to modify the thread. 1665 Mirror-thread titles, descriptions, and notification state remain editable 1666 by privileged app viewers. Mirror metadata, visibility, and membership are 1667 provider-managed and cannot be changed through this endpoint. 1668 1669 Args: 1670 thread: Thread ID (`thr_...`). The authenticated user must have permission to update this thread. 1671 input: Request body. 1672 input.description: Optional longer text describing the thread's purpose. Replaces the existing description when provided. 1673 input.metadata: Arbitrary key-value metadata to store on the thread. Merged with or replaces existing metadata. 1674 input.muted: When `true`, suppresses notifications for new messages in this thread for the authenticated user. 1675 input.profile_picture: New profile picture for the thread. Provide all three inner fields to replace the existing image. 1676 input.title: Human-readable display name for the thread. Replaces the existing title when provided. 1677 input.visibility: Widen a team-owned thread: `private` may become `restricted` or `team`, and `restricted` may become `team`. Visibility cannot be narrowed. 1678 1679 Returns: 1680 The thread object after the update has been applied. 1681 """ 1682 return self._http.request( 1683 f"/api/v1/threads/{thread}", 1684 method="PUT", 1685 body=input, 1686 response_type=Thread, 1687 ) 1688 1689 def agents(self, thread: str) -> ThreadAgentsResponse: 1690 """ 1691 List agents in a thread 1692 Returns the agents participating in the specified thread. Only personal user 1693 threads (threads owned by a single user, not a team) expose agents through 1694 this endpoint; requests for team threads return 404. 1695 The authenticated user must have visibility into the thread. Each agent entry 1696 includes display information such as name and profile picture. Thread-level 1697 overrides (e.g. a custom name or profile picture set for this thread) take 1698 precedence over the agent's default values. When the caller is the thread 1699 owner, each entry also includes an `agent_config` object describing the 1700 agent's message policy and context configuration. 1701 1702 Args: 1703 thread: Thread ID (`thr_...`). Must be a personal user thread visible to the authenticated user. 1704 1705 Returns: 1706 Successful response 1707 """ 1708 return self._http.request( 1709 f"/api/v1/threads/{thread}/agents", 1710 response_type=ThreadAgentsResponse, 1711 ) 1712 1713 def artifacts(self, thread: str) -> ThreadArtifactsResponse: 1714 """ 1715 List artifacts for a thread 1716 Returns all artifacts produced during a thread's AI conversation. Artifacts are 1717 structured outputs such as code files, documents, or generated assets created 1718 by the AI agent in response to messages in the thread. 1719 The authenticated user must have access to the specified thread. Results are 1720 returned in a single page; there is no cursor-based pagination for this endpoint. 1721 1722 Args: 1723 thread: Thread ID (`thr_...`). Must be accessible to the authenticated user. 1724 1725 Returns: 1726 Successful response 1727 """ 1728 return self._http.request( 1729 f"/api/v1/threads/{thread}/artifacts", 1730 response_type=ThreadArtifactsResponse, 1731 ) 1732 1733 def mark_read(self, thread: str, input: ThreadMarkReadInput) -> None: 1734 """ 1735 Mark a thread as read 1736 Records that a user has read up to a specific message in the thread. Unread 1737 indicators and badge counts are cleared up to the specified message. 1738 You must supply exactly one of `last_read_message` or `use_latest_message`. 1739 Omitting both returns 400. If `use_latest_message` is `true` and the thread 1740 has no messages, the request succeeds silently with no state change. 1741 For server-to-server (S2S) requests where no user identity is present in the 1742 token, the `user` param is required to identify whose read state to update. 1743 1744 Args: 1745 thread: Thread ID (`thr_...`). The thread to mark as read. 1746 input: Request body. 1747 input.last_read_message: Message ID (`msg_...`) to record as the last read message. Mutually exclusive with `use_latest_message`. 1748 input.use_latest_message: When `true`, marks the thread as read up to the latest message. Mutually exclusive with `last_read_message`. 1749 input.user: User ID (`usr_...`) whose read state to update. Required for S2S requests; ignored when an authenticated user is present in the token. 1750 1751 Returns: 1752 Empty response on success. 1753 """ 1754 self._http.request(f"/api/v1/threads/{thread}/mark_read", method="POST", body=input) 1755 1756 def messages( 1757 self, 1758 thread: str, 1759 *, 1760 before_cursor: str | None = None, 1761 after_cursor: str | None = None, 1762 metadata: dict[str, Any] | None = None, 1763 limit: int | None = None, 1764 anchor: str | None = None, 1765 direction: Literal["before", "after", "around"] | None = None, 1766 before_limit: int | None = None, 1767 after_limit: int | None = None, 1768 include_anchor: bool | None = None, 1769 anchor_agent_mode: Literal["cli", "embedded"] | None = None, 1770 anchor_agent: str | None = None, 1771 include_reply_counts: bool | None = None, 1772 ) -> ThreadMessagesResponse: 1773 """ 1774 List messages in a thread 1775 Returns a cursor-paginated list of messages belonging to the specified thread, 1776 ordered from oldest to newest. Supply `before_cursor`, `after_cursor`, or both 1777 to page through or bound the result set; omit both to receive the most recent page. 1778 Supply `anchor` and `direction` to fetch a window before, after, or around a 1779 specific message. Use `anchor=last_matching&anchor_agent_mode=embedded` to 1780 resolve the anchor from the latest embedded-agent message, and add 1781 `anchor_agent` to scope that resolution to a single sender agent. 1782 Supply `metadata` as a JSON-encoded structured expression to filter message 1783 metadata before cursor pagination or anchored window limits are applied. 1784 The authenticated user must have access to the thread's owner (workspace or user). 1785 A 403 is returned if the thread exists but is not accessible to the caller; a 404 1786 is returned if the thread does not exist or is not visible to the authenticated user. 1787 Pass `include_reply_counts: true` to annotate each message with the number of 1788 threaded replies it has received. This adds a small amount of latency and should 1789 be omitted when reply counts are not needed. 1790 1791 Args: 1792 thread: Thread ID (`thr_...`). The authenticated user must have access to this thread. 1793 before_cursor: Opaque cursor returned in a previous response's `before_cursor` field. When provided, returns messages immediately before that position. May be combined with `after_cursor` to bound a range. 1794 after_cursor: Opaque cursor returned in a previous response's `after_cursor` field. When provided, returns messages immediately after that position. May be combined with `before_cursor` to bound a range. 1795 metadata: Structured metadata filter expression. Only messages whose `metadata` object satisfies the expression are returned. The filter is applied before cursor pagination and anchored window limits. 1796 limit: Maximum number of messages to return per page. Defaults to 20; maximum is 100. 1797 anchor: Message ID (`msg_...`) to use as a window anchor, or `last_matching` to resolve the anchor from the latest message matching the anchor filters. Cannot be combined with `before_cursor` or `after_cursor`. 1798 direction: Window direction relative to `anchor`. `before` returns older messages, `after` returns newer messages, and `around` returns messages on both sides. Defaults to `after` when `anchor` is supplied. `direction=around` cannot be combined with an explicit `limit`; use `before_limit` and `after_limit`. 1799 before_limit: For `direction=around`, maximum number of messages older than the anchor. Defaults to 20; maximum is 100. 1800 after_limit: For `direction=around`, maximum number of messages newer than the anchor. Defaults to 20; maximum is 100. 1801 include_anchor: Whether to include the anchor message in a window response. Defaults to `true` for `direction=around`; ignored for ordinary cursor pagination and one-sided windows. 1802 anchor_agent_mode: When `anchor=last_matching`, resolve the anchor from the latest message with this local agent execution mode. 1803 anchor_agent: When `anchor=last_matching`, scope the anchor resolution to messages sent by this agent (`agi_...`). Combine with `anchor_agent_mode` to resolve the latest message from a specific agent in a given mode. 1804 include_reply_counts: When `true`, each message in the response is annotated with its threaded reply count. Defaults to `false`. Adds latency; omit when reply counts are not needed. 1805 1806 Returns: 1807 Successful response 1808 """ 1809 query: dict[str, object] = {} 1810 if before_cursor is not None: 1811 query["before_cursor"] = before_cursor 1812 if after_cursor is not None: 1813 query["after_cursor"] = after_cursor 1814 if metadata is not None: 1815 query["metadata"] = metadata 1816 if limit is not None: 1817 query["limit"] = limit 1818 if anchor is not None: 1819 query["anchor"] = anchor 1820 if direction is not None: 1821 query["direction"] = direction 1822 if before_limit is not None: 1823 query["before_limit"] = before_limit 1824 if after_limit is not None: 1825 query["after_limit"] = after_limit 1826 if include_anchor is not None: 1827 query["include_anchor"] = include_anchor 1828 if anchor_agent_mode is not None: 1829 query["anchor_agent_mode"] = anchor_agent_mode 1830 if anchor_agent is not None: 1831 query["anchor_agent"] = anchor_agent 1832 if include_reply_counts is not None: 1833 query["include_reply_counts"] = include_reply_counts 1834 return self._http.request( 1835 f"/api/v1/threads/{thread}/messages", 1836 query=query, 1837 response_type=ThreadMessagesResponse, 1838 ) 1839 1840 def picture(self, thread: str, input: ThreadPictureInput) -> Thread: 1841 """ 1842 Update a thread's profile picture 1843 Uploads a new profile picture for the specified thread and returns the updated 1844 thread object. The image must be supplied as a base64-encoded string with its 1845 MIME type. 1846 The authenticated user must own the thread or be a team owner of the workspace 1847 the thread belongs to. Supplying invalid base64 data returns 422. 1848 1849 Args: 1850 thread: Thread ID (`thr_...`). The authenticated user must have permission to update this thread. 1851 input: Request body. 1852 input.picture: Profile picture payload. Must include the base64-encoded image data and its MIME type. 1853 1854 Returns: 1855 The thread object after the profile picture has been updated. 1856 """ 1857 return self._http.request( 1858 f"/api/v1/threads/{thread}/picture", 1859 method="PUT", 1860 body=input, 1861 response_type=Thread, 1862 ) 1863 1864 def read_status(self, thread: str, *, user: str | None = None) -> ThreadReadStatus: 1865 """ 1866 Retrieve a thread's read status 1867 Returns the read status of a thread for the specified user, including the ID 1868 of the last message they have read and the number of unread messages remaining. 1869 For user-authenticated requests, the status is always returned for the 1870 authenticated user and the `user` parameter is ignored. For server-to-server 1871 (S2S) requests, the `user` parameter is required and must be a valid user ID. 1872 Returns 404 if the thread does not exist or the caller does not have access 1873 to it. 1874 1875 Args: 1876 thread: Thread ID (`thr_...`). Must be accessible to the authenticated user or, for S2S requests, to the specified user. 1877 user: User ID (`usr_...`) whose read status to retrieve. Required for S2S requests; ignored for user-authenticated requests, which always return the status for the authenticated user. 1878 1879 Returns: 1880 The read status record for the requested thread and user. 1881 """ 1882 query: dict[str, object] = {} 1883 if user is not None: 1884 query["user"] = user 1885 return self._http.request( 1886 f"/api/v1/threads/{thread}/read_status", 1887 query=query, 1888 response_type=ThreadReadStatus, 1889 ) 1890 1891 def search( 1892 self, 1893 thread: str, 1894 q: str, 1895 *, 1896 app: str | None = None, 1897 limit: int | None = None, 1898 mode: Literal["text", "embedding", "hybrid"] | None = None, 1899 before_cursor: str | None = None, 1900 after_cursor: str | None = None, 1901 ) -> ThreadSearchResponse: 1902 """ 1903 Search messages in a thread 1904 Searches canonical message content in the specified thread. `"text"` mode 1905 performs the existing case-insensitive substring search, `"embedding"` ranks 1906 stored message embeddings by cosine similarity, and `"hybrid"` combines the 1907 text and embedding rankings with Reciprocal Rank Fusion (RRF). Only messages 1908 visible to the authenticated caller are considered. 1909 Results are intentionally lean: each row contains only a bounded content 1910 snippet, sender identity, and timestamp. Attachments, reactions, ACLs, and 1911 metadata are neither hydrated nor serialized. At most 20 results are 1912 returned. Text results support chronological cursor pagination. Embedding and 1913 hybrid results are relevance-ranked single pages and return null cursors. 1914 1915 Args: 1916 thread: Thread ID (`thr_...`). Must be visible to the authenticated caller. 1917 app: App ID (`app_...`). Required by the protected developer mount and omitted from the public mount. 1918 q: Text or semantic search query. Must contain 3 to 200 characters after trimming. 1919 limit: Maximum number of results. Defaults to 20 and is capped at 20. 1920 mode: Search algorithm: `text` for substring matching, `embedding` for cosine similarity, or `hybrid` for RRF over both rankings. 1921 before_cursor: Text mode only. Opaque cursor returned by a previous page; fetches older matches. 1922 after_cursor: Text mode only. Opaque cursor returned by a previous page; fetches newer matches. 1923 1924 Returns: 1925 Successful response 1926 """ 1927 query: dict[str, object] = {} 1928 if app is not None: 1929 query["app"] = app 1930 query["q"] = q 1931 if limit is not None: 1932 query["limit"] = limit 1933 if mode is not None: 1934 query["mode"] = mode 1935 if before_cursor is not None: 1936 query["before_cursor"] = before_cursor 1937 if after_cursor is not None: 1938 query["after_cursor"] = after_cursor 1939 return self._http.request( 1940 f"/api/v1/threads/{thread}/search", 1941 query=query, 1942 response_type=ThreadSearchResponse, 1943 ) 1944 1945 def trajectories( 1946 self, 1947 thread: str, 1948 *, 1949 before_cursor: str | None = None, 1950 after_cursor: str | None = None, 1951 limit: int | None = None, 1952 message: str | None = None, 1953 ) -> ThreadTrajectoriesResponse: 1954 """ 1955 List trajectories for a thread 1956 Returns a cursor-paginated list of thread message trajectories associated with the 1957 specified thread. Each trajectory links a user message and its agent response to the 1958 underlying AI trajectory record that captured the model's reasoning steps. 1959 The authenticated user must own the thread or be a member of the workspace it belongs 1960 to. Results are returned in reverse chronological order by default. Use `before_cursor` 1961 and `after_cursor` to navigate pages; provide at most one cursor per request. 1962 Optionally filter results to trajectories produced in response to a specific message 1963 by supplying the `message` parameter. When no trajectories match the query, `data` 1964 is an empty array and both cursor fields are `null`. A cursor that cannot be decoded 1965 returns a 400 `invalid_cursor` error. 1966 1967 Args: 1968 thread: Thread ID (`thr_...`). The authenticated user must own this thread or belong to its workspace. 1969 before_cursor: Opaque cursor from a previous response's `before_cursor` field. Returns the page of results preceding that cursor position. 1970 after_cursor: Opaque cursor from a previous response's `after_cursor` field. Returns the page of results following that cursor position. 1971 limit: Maximum number of trajectories to return per page. Defaults to 20; maximum is 100. 1972 message: Message ID (`msg_...`). When provided, limits results to trajectories associated with this specific message. 1973 1974 Returns: 1975 Successful response 1976 """ 1977 query: dict[str, object] = {} 1978 if before_cursor is not None: 1979 query["before_cursor"] = before_cursor 1980 if after_cursor is not None: 1981 query["after_cursor"] = after_cursor 1982 if limit is not None: 1983 query["limit"] = limit 1984 if message is not None: 1985 query["message"] = message 1986 return self._http.request( 1987 f"/api/v1/threads/{thread}/trajectories", 1988 query=query, 1989 response_type=ThreadTrajectoriesResponse, 1990 )
1619 def delete(self, thread: str) -> None: 1620 """ 1621 Delete a thread 1622 Permanently deletes a thread and all of its messages and artifacts. This action 1623 cannot be undone. 1624 The authenticated user must own the thread or be an owner of the team the thread 1625 belongs to. Attempting to delete a thread owned by another user or team returns 403. 1626 1627 Args: 1628 thread: Thread ID (`thr_...`). The authenticated user must own this thread. 1629 1630 Returns: 1631 Empty response on successful deletion. 1632 """ 1633 self._http.request(f"/api/v1/threads/{thread}", method="DELETE")
Delete a thread Permanently deletes a thread and all of its messages and artifacts. This action cannot be undone. The authenticated user must own the thread or be an owner of the team the thread belongs to. Attempting to delete a thread owned by another user or team returns 403.
Arguments:
- thread: Thread ID (
thr_...). The authenticated user must own this thread.
Returns:
Empty response on successful deletion.
1635 def get(self, thread: str) -> Thread: 1636 """ 1637 Retrieve a thread 1638 Returns the full thread record for the given thread ID. The authenticated user 1639 must own the thread or be a member of the workspace it belongs to. 1640 Use this endpoint to fetch the current state of a single thread, including its 1641 title, description, and metadata. To list many threads, use the list endpoint 1642 with cursor-based pagination. 1643 1644 Args: 1645 thread: Thread ID (`thr_...`). The authenticated user must have access to this thread. 1646 1647 Returns: 1648 The requested thread object. 1649 """ 1650 return self._http.request(f"/api/v1/threads/{thread}", response_type=Thread)
Retrieve a thread Returns the full thread record for the given thread ID. The authenticated user must own the thread or be a member of the workspace it belongs to. Use this endpoint to fetch the current state of a single thread, including its title, description, and metadata. To list many threads, use the list endpoint with cursor-based pagination.
Arguments:
- thread: Thread ID (
thr_...). The authenticated user must have access to this thread.
Returns:
The requested thread object.
1652 def replace(self, thread: str, input: ThreadReplaceInput) -> Thread: 1653 """ 1654 Update a thread 1655 Updates one or more mutable properties of the specified thread and returns 1656 the full thread object with the applied changes. Only the fields you provide 1657 are modified; omitted fields retain their current values. 1658 If `profile_picture` is supplied, the image is uploaded before the other 1659 fields are saved, after all ordinary thread fields have passed validation. 1660 Supplying invalid base64 picture data returns 422 and no other fields are 1661 updated. 1662 Visibility can only widen: `private` may become `restricted` or `team`, and 1663 `restricted` may become `team`. The authenticated viewer must have 1664 permission to modify the thread. 1665 Mirror-thread titles, descriptions, and notification state remain editable 1666 by privileged app viewers. Mirror metadata, visibility, and membership are 1667 provider-managed and cannot be changed through this endpoint. 1668 1669 Args: 1670 thread: Thread ID (`thr_...`). The authenticated user must have permission to update this thread. 1671 input: Request body. 1672 input.description: Optional longer text describing the thread's purpose. Replaces the existing description when provided. 1673 input.metadata: Arbitrary key-value metadata to store on the thread. Merged with or replaces existing metadata. 1674 input.muted: When `true`, suppresses notifications for new messages in this thread for the authenticated user. 1675 input.profile_picture: New profile picture for the thread. Provide all three inner fields to replace the existing image. 1676 input.title: Human-readable display name for the thread. Replaces the existing title when provided. 1677 input.visibility: Widen a team-owned thread: `private` may become `restricted` or `team`, and `restricted` may become `team`. Visibility cannot be narrowed. 1678 1679 Returns: 1680 The thread object after the update has been applied. 1681 """ 1682 return self._http.request( 1683 f"/api/v1/threads/{thread}", 1684 method="PUT", 1685 body=input, 1686 response_type=Thread, 1687 )
Update a thread
Updates one or more mutable properties of the specified thread and returns
the full thread object with the applied changes. Only the fields you provide
are modified; omitted fields retain their current values.
If profile_picture is supplied, the image is uploaded before the other
fields are saved, after all ordinary thread fields have passed validation.
Supplying invalid base64 picture data returns 422 and no other fields are
updated.
Visibility can only widen: private may become restricted or team, and
restricted may become team. The authenticated viewer must have
permission to modify the thread.
Mirror-thread titles, descriptions, and notification state remain editable
by privileged app viewers. Mirror metadata, visibility, and membership are
provider-managed and cannot be changed through this endpoint.
Arguments:
- thread: Thread ID (
thr_...). The authenticated user must have permission to update this thread. - input: Request body.
- input.description: Optional longer text describing the thread's purpose. Replaces the existing description when provided.
- input.metadata: Arbitrary key-value metadata to store on the thread. Merged with or replaces existing metadata.
- input.muted: When
true, suppresses notifications for new messages in this thread for the authenticated user. - input.profile_picture: New profile picture for the thread. Provide all three inner fields to replace the existing image.
- input.title: Human-readable display name for the thread. Replaces the existing title when provided.
- input.visibility: Widen a team-owned thread:
privatemay becomerestrictedorteam, andrestrictedmay becometeam. Visibility cannot be narrowed.
Returns:
The thread object after the update has been applied.
1689 def agents(self, thread: str) -> ThreadAgentsResponse: 1690 """ 1691 List agents in a thread 1692 Returns the agents participating in the specified thread. Only personal user 1693 threads (threads owned by a single user, not a team) expose agents through 1694 this endpoint; requests for team threads return 404. 1695 The authenticated user must have visibility into the thread. Each agent entry 1696 includes display information such as name and profile picture. Thread-level 1697 overrides (e.g. a custom name or profile picture set for this thread) take 1698 precedence over the agent's default values. When the caller is the thread 1699 owner, each entry also includes an `agent_config` object describing the 1700 agent's message policy and context configuration. 1701 1702 Args: 1703 thread: Thread ID (`thr_...`). Must be a personal user thread visible to the authenticated user. 1704 1705 Returns: 1706 Successful response 1707 """ 1708 return self._http.request( 1709 f"/api/v1/threads/{thread}/agents", 1710 response_type=ThreadAgentsResponse, 1711 )
List agents in a thread
Returns the agents participating in the specified thread. Only personal user
threads (threads owned by a single user, not a team) expose agents through
this endpoint; requests for team threads return 404.
The authenticated user must have visibility into the thread. Each agent entry
includes display information such as name and profile picture. Thread-level
overrides (e.g. a custom name or profile picture set for this thread) take
precedence over the agent's default values. When the caller is the thread
owner, each entry also includes an agent_config object describing the
agent's message policy and context configuration.
Arguments:
- thread: Thread ID (
thr_...). Must be a personal user thread visible to the authenticated user.
Returns:
Successful response
1713 def artifacts(self, thread: str) -> ThreadArtifactsResponse: 1714 """ 1715 List artifacts for a thread 1716 Returns all artifacts produced during a thread's AI conversation. Artifacts are 1717 structured outputs such as code files, documents, or generated assets created 1718 by the AI agent in response to messages in the thread. 1719 The authenticated user must have access to the specified thread. Results are 1720 returned in a single page; there is no cursor-based pagination for this endpoint. 1721 1722 Args: 1723 thread: Thread ID (`thr_...`). Must be accessible to the authenticated user. 1724 1725 Returns: 1726 Successful response 1727 """ 1728 return self._http.request( 1729 f"/api/v1/threads/{thread}/artifacts", 1730 response_type=ThreadArtifactsResponse, 1731 )
List artifacts for a thread Returns all artifacts produced during a thread's AI conversation. Artifacts are structured outputs such as code files, documents, or generated assets created by the AI agent in response to messages in the thread. The authenticated user must have access to the specified thread. Results are returned in a single page; there is no cursor-based pagination for this endpoint.
Arguments:
- thread: Thread ID (
thr_...). Must be accessible to the authenticated user.
Returns:
Successful response
1733 def mark_read(self, thread: str, input: ThreadMarkReadInput) -> None: 1734 """ 1735 Mark a thread as read 1736 Records that a user has read up to a specific message in the thread. Unread 1737 indicators and badge counts are cleared up to the specified message. 1738 You must supply exactly one of `last_read_message` or `use_latest_message`. 1739 Omitting both returns 400. If `use_latest_message` is `true` and the thread 1740 has no messages, the request succeeds silently with no state change. 1741 For server-to-server (S2S) requests where no user identity is present in the 1742 token, the `user` param is required to identify whose read state to update. 1743 1744 Args: 1745 thread: Thread ID (`thr_...`). The thread to mark as read. 1746 input: Request body. 1747 input.last_read_message: Message ID (`msg_...`) to record as the last read message. Mutually exclusive with `use_latest_message`. 1748 input.use_latest_message: When `true`, marks the thread as read up to the latest message. Mutually exclusive with `last_read_message`. 1749 input.user: User ID (`usr_...`) whose read state to update. Required for S2S requests; ignored when an authenticated user is present in the token. 1750 1751 Returns: 1752 Empty response on success. 1753 """ 1754 self._http.request(f"/api/v1/threads/{thread}/mark_read", method="POST", body=input)
Mark a thread as read
Records that a user has read up to a specific message in the thread. Unread
indicators and badge counts are cleared up to the specified message.
You must supply exactly one of last_read_message or use_latest_message.
Omitting both returns 400. If use_latest_message is true and the thread
has no messages, the request succeeds silently with no state change.
For server-to-server (S2S) requests where no user identity is present in the
token, the user param is required to identify whose read state to update.
Arguments:
- thread: Thread ID (
thr_...). The thread to mark as read. - input: Request body.
- input.last_read_message: Message ID (
msg_...) to record as the last read message. Mutually exclusive withuse_latest_message. - input.use_latest_message: When
true, marks the thread as read up to the latest message. Mutually exclusive withlast_read_message. - input.user: User ID (
usr_...) whose read state to update. Required for S2S requests; ignored when an authenticated user is present in the token.
Returns:
Empty response on success.
1756 def messages( 1757 self, 1758 thread: str, 1759 *, 1760 before_cursor: str | None = None, 1761 after_cursor: str | None = None, 1762 metadata: dict[str, Any] | None = None, 1763 limit: int | None = None, 1764 anchor: str | None = None, 1765 direction: Literal["before", "after", "around"] | None = None, 1766 before_limit: int | None = None, 1767 after_limit: int | None = None, 1768 include_anchor: bool | None = None, 1769 anchor_agent_mode: Literal["cli", "embedded"] | None = None, 1770 anchor_agent: str | None = None, 1771 include_reply_counts: bool | None = None, 1772 ) -> ThreadMessagesResponse: 1773 """ 1774 List messages in a thread 1775 Returns a cursor-paginated list of messages belonging to the specified thread, 1776 ordered from oldest to newest. Supply `before_cursor`, `after_cursor`, or both 1777 to page through or bound the result set; omit both to receive the most recent page. 1778 Supply `anchor` and `direction` to fetch a window before, after, or around a 1779 specific message. Use `anchor=last_matching&anchor_agent_mode=embedded` to 1780 resolve the anchor from the latest embedded-agent message, and add 1781 `anchor_agent` to scope that resolution to a single sender agent. 1782 Supply `metadata` as a JSON-encoded structured expression to filter message 1783 metadata before cursor pagination or anchored window limits are applied. 1784 The authenticated user must have access to the thread's owner (workspace or user). 1785 A 403 is returned if the thread exists but is not accessible to the caller; a 404 1786 is returned if the thread does not exist or is not visible to the authenticated user. 1787 Pass `include_reply_counts: true` to annotate each message with the number of 1788 threaded replies it has received. This adds a small amount of latency and should 1789 be omitted when reply counts are not needed. 1790 1791 Args: 1792 thread: Thread ID (`thr_...`). The authenticated user must have access to this thread. 1793 before_cursor: Opaque cursor returned in a previous response's `before_cursor` field. When provided, returns messages immediately before that position. May be combined with `after_cursor` to bound a range. 1794 after_cursor: Opaque cursor returned in a previous response's `after_cursor` field. When provided, returns messages immediately after that position. May be combined with `before_cursor` to bound a range. 1795 metadata: Structured metadata filter expression. Only messages whose `metadata` object satisfies the expression are returned. The filter is applied before cursor pagination and anchored window limits. 1796 limit: Maximum number of messages to return per page. Defaults to 20; maximum is 100. 1797 anchor: Message ID (`msg_...`) to use as a window anchor, or `last_matching` to resolve the anchor from the latest message matching the anchor filters. Cannot be combined with `before_cursor` or `after_cursor`. 1798 direction: Window direction relative to `anchor`. `before` returns older messages, `after` returns newer messages, and `around` returns messages on both sides. Defaults to `after` when `anchor` is supplied. `direction=around` cannot be combined with an explicit `limit`; use `before_limit` and `after_limit`. 1799 before_limit: For `direction=around`, maximum number of messages older than the anchor. Defaults to 20; maximum is 100. 1800 after_limit: For `direction=around`, maximum number of messages newer than the anchor. Defaults to 20; maximum is 100. 1801 include_anchor: Whether to include the anchor message in a window response. Defaults to `true` for `direction=around`; ignored for ordinary cursor pagination and one-sided windows. 1802 anchor_agent_mode: When `anchor=last_matching`, resolve the anchor from the latest message with this local agent execution mode. 1803 anchor_agent: When `anchor=last_matching`, scope the anchor resolution to messages sent by this agent (`agi_...`). Combine with `anchor_agent_mode` to resolve the latest message from a specific agent in a given mode. 1804 include_reply_counts: When `true`, each message in the response is annotated with its threaded reply count. Defaults to `false`. Adds latency; omit when reply counts are not needed. 1805 1806 Returns: 1807 Successful response 1808 """ 1809 query: dict[str, object] = {} 1810 if before_cursor is not None: 1811 query["before_cursor"] = before_cursor 1812 if after_cursor is not None: 1813 query["after_cursor"] = after_cursor 1814 if metadata is not None: 1815 query["metadata"] = metadata 1816 if limit is not None: 1817 query["limit"] = limit 1818 if anchor is not None: 1819 query["anchor"] = anchor 1820 if direction is not None: 1821 query["direction"] = direction 1822 if before_limit is not None: 1823 query["before_limit"] = before_limit 1824 if after_limit is not None: 1825 query["after_limit"] = after_limit 1826 if include_anchor is not None: 1827 query["include_anchor"] = include_anchor 1828 if anchor_agent_mode is not None: 1829 query["anchor_agent_mode"] = anchor_agent_mode 1830 if anchor_agent is not None: 1831 query["anchor_agent"] = anchor_agent 1832 if include_reply_counts is not None: 1833 query["include_reply_counts"] = include_reply_counts 1834 return self._http.request( 1835 f"/api/v1/threads/{thread}/messages", 1836 query=query, 1837 response_type=ThreadMessagesResponse, 1838 )
List messages in a thread
Returns a cursor-paginated list of messages belonging to the specified thread,
ordered from oldest to newest. Supply before_cursor, after_cursor, or both
to page through or bound the result set; omit both to receive the most recent page.
Supply anchor and direction to fetch a window before, after, or around a
specific message. Use anchor=last_matching&anchor_agent_mode=embedded to
resolve the anchor from the latest embedded-agent message, and add
anchor_agent to scope that resolution to a single sender agent.
Supply metadata as a JSON-encoded structured expression to filter message
metadata before cursor pagination or anchored window limits are applied.
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.
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.
Arguments:
- thread: Thread ID (
thr_...). The authenticated user must have access to this thread. - before_cursor: Opaque cursor returned in a previous response's
before_cursorfield. When provided, returns messages immediately before that position. May be combined withafter_cursorto bound a range. - after_cursor: Opaque cursor returned in a previous response's
after_cursorfield. When provided, returns messages immediately after that position. May be combined withbefore_cursorto bound a range. - metadata: Structured metadata filter expression. Only messages whose
metadataobject satisfies the expression are returned. The filter is applied before cursor pagination and anchored window limits. - limit: Maximum number of messages to return per page. Defaults to 20; maximum is 100.
- anchor: Message ID (
msg_...) to use as a window anchor, orlast_matchingto resolve the anchor from the latest message matching the anchor filters. Cannot be combined withbefore_cursororafter_cursor. - direction: Window direction relative to
anchor.beforereturns older messages,afterreturns newer messages, andaroundreturns messages on both sides. Defaults toafterwhenanchoris supplied.direction=aroundcannot be combined with an explicitlimit; usebefore_limitandafter_limit. - before_limit: For
direction=around, maximum number of messages older than the anchor. Defaults to 20; maximum is 100. - after_limit: For
direction=around, maximum number of messages newer than the anchor. Defaults to 20; maximum is 100. - include_anchor: Whether to include the anchor message in a window response. Defaults to
truefordirection=around; ignored for ordinary cursor pagination and one-sided windows. - anchor_agent_mode: When
anchor=last_matching, resolve the anchor from the latest message with this local agent execution mode. - anchor_agent: When
anchor=last_matching, scope the anchor resolution to messages sent by this agent (agi_...). Combine withanchor_agent_modeto resolve the latest message from a specific agent in a given mode. - include_reply_counts: When
true, each message in the response is annotated with its threaded reply count. Defaults tofalse. Adds latency; omit when reply counts are not needed.
Returns:
Successful response
1840 def picture(self, thread: str, input: ThreadPictureInput) -> Thread: 1841 """ 1842 Update a thread's profile picture 1843 Uploads a new profile picture for the specified thread and returns the updated 1844 thread object. The image must be supplied as a base64-encoded string with its 1845 MIME type. 1846 The authenticated user must own the thread or be a team owner of the workspace 1847 the thread belongs to. Supplying invalid base64 data returns 422. 1848 1849 Args: 1850 thread: Thread ID (`thr_...`). The authenticated user must have permission to update this thread. 1851 input: Request body. 1852 input.picture: Profile picture payload. Must include the base64-encoded image data and its MIME type. 1853 1854 Returns: 1855 The thread object after the profile picture has been updated. 1856 """ 1857 return self._http.request( 1858 f"/api/v1/threads/{thread}/picture", 1859 method="PUT", 1860 body=input, 1861 response_type=Thread, 1862 )
Update a thread's profile picture Uploads a new profile picture for the specified thread and returns the updated thread object. The image must be supplied as a base64-encoded string with its MIME type. The authenticated user must own the thread or be a team owner of the workspace the thread belongs to. Supplying invalid base64 data returns 422.
Arguments:
- thread: Thread ID (
thr_...). The authenticated user must have permission to update this thread. - input: Request body.
- input.picture: Profile picture payload. Must include the base64-encoded image data and its MIME type.
Returns:
The thread object after the profile picture has been updated.
1864 def read_status(self, thread: str, *, user: str | None = None) -> ThreadReadStatus: 1865 """ 1866 Retrieve a thread's read status 1867 Returns the read status of a thread for the specified user, including the ID 1868 of the last message they have read and the number of unread messages remaining. 1869 For user-authenticated requests, the status is always returned for the 1870 authenticated user and the `user` parameter is ignored. For server-to-server 1871 (S2S) requests, the `user` parameter is required and must be a valid user ID. 1872 Returns 404 if the thread does not exist or the caller does not have access 1873 to it. 1874 1875 Args: 1876 thread: Thread ID (`thr_...`). Must be accessible to the authenticated user or, for S2S requests, to the specified user. 1877 user: User ID (`usr_...`) whose read status to retrieve. Required for S2S requests; ignored for user-authenticated requests, which always return the status for the authenticated user. 1878 1879 Returns: 1880 The read status record for the requested thread and user. 1881 """ 1882 query: dict[str, object] = {} 1883 if user is not None: 1884 query["user"] = user 1885 return self._http.request( 1886 f"/api/v1/threads/{thread}/read_status", 1887 query=query, 1888 response_type=ThreadReadStatus, 1889 )
Retrieve a thread's read status
Returns the read status of a thread for the specified user, including the ID
of the last message they have read and the number of unread messages remaining.
For user-authenticated requests, the status is always returned for the
authenticated user and the user parameter is ignored. For server-to-server
(S2S) requests, the user parameter is required and must be a valid user ID.
Returns 404 if the thread does not exist or the caller does not have access
to it.
Arguments:
- thread: Thread ID (
thr_...). Must be accessible to the authenticated user or, for S2S requests, to the specified user. - user: User ID (
usr_...) whose read status to retrieve. Required for S2S requests; ignored for user-authenticated requests, which always return the status for the authenticated user.
Returns:
The read status record for the requested thread and user.
1891 def search( 1892 self, 1893 thread: str, 1894 q: str, 1895 *, 1896 app: str | None = None, 1897 limit: int | None = None, 1898 mode: Literal["text", "embedding", "hybrid"] | None = None, 1899 before_cursor: str | None = None, 1900 after_cursor: str | None = None, 1901 ) -> ThreadSearchResponse: 1902 """ 1903 Search messages in a thread 1904 Searches canonical message content in the specified thread. `"text"` mode 1905 performs the existing case-insensitive substring search, `"embedding"` ranks 1906 stored message embeddings by cosine similarity, and `"hybrid"` combines the 1907 text and embedding rankings with Reciprocal Rank Fusion (RRF). Only messages 1908 visible to the authenticated caller are considered. 1909 Results are intentionally lean: each row contains only a bounded content 1910 snippet, sender identity, and timestamp. Attachments, reactions, ACLs, and 1911 metadata are neither hydrated nor serialized. At most 20 results are 1912 returned. Text results support chronological cursor pagination. Embedding and 1913 hybrid results are relevance-ranked single pages and return null cursors. 1914 1915 Args: 1916 thread: Thread ID (`thr_...`). Must be visible to the authenticated caller. 1917 app: App ID (`app_...`). Required by the protected developer mount and omitted from the public mount. 1918 q: Text or semantic search query. Must contain 3 to 200 characters after trimming. 1919 limit: Maximum number of results. Defaults to 20 and is capped at 20. 1920 mode: Search algorithm: `text` for substring matching, `embedding` for cosine similarity, or `hybrid` for RRF over both rankings. 1921 before_cursor: Text mode only. Opaque cursor returned by a previous page; fetches older matches. 1922 after_cursor: Text mode only. Opaque cursor returned by a previous page; fetches newer matches. 1923 1924 Returns: 1925 Successful response 1926 """ 1927 query: dict[str, object] = {} 1928 if app is not None: 1929 query["app"] = app 1930 query["q"] = q 1931 if limit is not None: 1932 query["limit"] = limit 1933 if mode is not None: 1934 query["mode"] = mode 1935 if before_cursor is not None: 1936 query["before_cursor"] = before_cursor 1937 if after_cursor is not None: 1938 query["after_cursor"] = after_cursor 1939 return self._http.request( 1940 f"/api/v1/threads/{thread}/search", 1941 query=query, 1942 response_type=ThreadSearchResponse, 1943 )
Search messages in a thread
Searches canonical message content in the specified thread. "text" mode
performs the existing case-insensitive substring search, "embedding" ranks
stored message embeddings by cosine similarity, and "hybrid" combines the
text and embedding rankings with Reciprocal Rank Fusion (RRF). Only messages
visible to the authenticated caller are considered.
Results are intentionally lean: each row contains only a bounded content
snippet, sender identity, and timestamp. Attachments, reactions, ACLs, and
metadata are neither hydrated nor serialized. At most 20 results are
returned. Text results support chronological cursor pagination. Embedding and
hybrid results are relevance-ranked single pages and return null cursors.
Arguments:
- thread: Thread ID (
thr_...). Must be visible to the authenticated caller. - app: App ID (
app_...). Required by the protected developer mount and omitted from the public mount. - q: Text or semantic search query. Must contain 3 to 200 characters after trimming.
- limit: Maximum number of results. Defaults to 20 and is capped at 20.
- mode: Search algorithm:
textfor substring matching,embeddingfor cosine similarity, orhybridfor RRF over both rankings. - before_cursor: Text mode only. Opaque cursor returned by a previous page; fetches older matches.
- after_cursor: Text mode only. Opaque cursor returned by a previous page; fetches newer matches.
Returns:
Successful response
1945 def trajectories( 1946 self, 1947 thread: str, 1948 *, 1949 before_cursor: str | None = None, 1950 after_cursor: str | None = None, 1951 limit: int | None = None, 1952 message: str | None = None, 1953 ) -> ThreadTrajectoriesResponse: 1954 """ 1955 List trajectories for a thread 1956 Returns a cursor-paginated list of thread message trajectories associated with the 1957 specified thread. Each trajectory links a user message and its agent response to the 1958 underlying AI trajectory record that captured the model's reasoning steps. 1959 The authenticated user must own the thread or be a member of the workspace it belongs 1960 to. Results are returned in reverse chronological order by default. Use `before_cursor` 1961 and `after_cursor` to navigate pages; provide at most one cursor per request. 1962 Optionally filter results to trajectories produced in response to a specific message 1963 by supplying the `message` parameter. When no trajectories match the query, `data` 1964 is an empty array and both cursor fields are `null`. A cursor that cannot be decoded 1965 returns a 400 `invalid_cursor` error. 1966 1967 Args: 1968 thread: Thread ID (`thr_...`). The authenticated user must own this thread or belong to its workspace. 1969 before_cursor: Opaque cursor from a previous response's `before_cursor` field. Returns the page of results preceding that cursor position. 1970 after_cursor: Opaque cursor from a previous response's `after_cursor` field. Returns the page of results following that cursor position. 1971 limit: Maximum number of trajectories to return per page. Defaults to 20; maximum is 100. 1972 message: Message ID (`msg_...`). When provided, limits results to trajectories associated with this specific message. 1973 1974 Returns: 1975 Successful response 1976 """ 1977 query: dict[str, object] = {} 1978 if before_cursor is not None: 1979 query["before_cursor"] = before_cursor 1980 if after_cursor is not None: 1981 query["after_cursor"] = after_cursor 1982 if limit is not None: 1983 query["limit"] = limit 1984 if message is not None: 1985 query["message"] = message 1986 return self._http.request( 1987 f"/api/v1/threads/{thread}/trajectories", 1988 query=query, 1989 response_type=ThreadTrajectoriesResponse, 1990 )
List trajectories for a thread
Returns a cursor-paginated list of thread message trajectories associated with the
specified thread. Each trajectory links a user message and its agent response to the
underlying AI trajectory record that captured the model's reasoning steps.
The authenticated user must own the thread or be a member of the workspace it belongs
to. Results are returned in reverse chronological order by default. Use before_cursor
and after_cursor to navigate pages; provide at most one cursor per request.
Optionally filter results to trajectories produced in response to a specific message
by supplying the message parameter. When no trajectories match the query, data
is an empty array and both cursor fields are null. A cursor that cannot be decoded
returns a 400 invalid_cursor error.
Arguments:
- thread: Thread ID (
thr_...). The authenticated user must own this thread or belong to its workspace. - before_cursor: Opaque cursor from a previous response's
before_cursorfield. Returns the page of results preceding that cursor position. - after_cursor: Opaque cursor from a previous response's
after_cursorfield. Returns the page of results following that cursor position. - limit: Maximum number of trajectories to return per page. Defaults to 20; maximum is 100.
- message: Message ID (
msg_...). When provided, limits results to trajectories associated with this specific message.
Returns:
Successful response