archastro.platform.v1.resources.thread_messages
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: b91c191bc4f5 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.common import Message, PaginatedReplies 14from ...types.threads import ThreadMessage 15 16 17class ReactionCreateInput(TypedDict): 18 "Add a reaction to a thread message" 19 20 emoji: str 21 'Emoji character or shortcode to add as a reaction, e.g. `" "` or `":thumbsup:"`.' 22 23 24class ThreadMessageReplaceInputAclAddItem(TypedDict, total=False): 25 actions: Required[list[str]] 26 'Array of action strings the principal is permitted to perform, e.g. `["read", "write"]`. Must contain at least one entry.' 27 principal: str | None 28 '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"`.' 29 principal_type: Required[str] 30 'The kind of principal receiving the grant. One of `"user"`, `"team"`, `"org"`, `"org_role"`, `"agent"`, or `"everyone"`.' 31 32 33class ThreadMessageReplaceInputAclGrantsItem(TypedDict, total=False): 34 actions: Required[list[str]] 35 'Array of action strings the principal is permitted to perform, e.g. `["read", "write"]`. Must contain at least one entry.' 36 principal: str | None 37 '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"`.' 38 principal_type: Required[str] 39 'The kind of principal receiving the grant. One of `"user"`, `"team"`, `"org"`, `"org_role"`, `"agent"`, or `"everyone"`.' 40 41 42class ThreadMessageReplaceInputAclRemoveItem(TypedDict, total=False): 43 principal: str | None 44 '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"`.' 45 principal_type: Required[str] 46 'The kind of principal to remove. One of `"user"`, `"team"`, `"org"`, `"org_role"`, `"agent"`, or `"everyone"`.' 47 48 49class ThreadMessageReplaceInputAcl(TypedDict, total=False): 50 add: list[ThreadMessageReplaceInputAclAddItem] | None 51 "Patch mode: grants to add or merge into the existing list. Cannot be combined with `grants`." 52 grants: list[ThreadMessageReplaceInputAclGrantsItem] | None 53 "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`." 54 remove: list[ThreadMessageReplaceInputAclRemoveItem] | None 55 "Patch mode: principals whose grants should be removed from the existing list. Cannot be combined with `grants`." 56 57 58class ThreadMessageReplaceInput(TypedDict, total=False): 59 "Update a thread message" 60 61 acl: ThreadMessageReplaceInputAcl | None 62 "Access control list for a private message (replace or patch grants). Only valid when the message is already `private`. Omit to leave unchanged." 63 content: str | None 64 "Replacement text content for the message. Omit to leave the content unchanged." 65 metadata: dict[str, Any] | None 66 "Replacement key-value metadata. Keys beginning with `sys:` are reserved and stripped." 67 type: str | None 68 "Replacement client-defined classification. Free-form string up to 64 characters; platform-reserved values such as `system` are rejected." 69 visibility: Literal["default", "private"] | None 70 "Create-time message visibility. Supplying the existing value is harmless, but changing between `default` and `private` returns 422." 71 72 73class ReactionCreateResponseData(BaseModel): 74 created_at: datetime | None = Field( 75 default=None, description="When the reaction was added (ISO 8601)." 76 ) 77 feedback_type: str | None = Field( 78 default=None, 79 description='Category of feedback. Currently `"emoji_reaction"` for emoji responses.', 80 ) 81 id: str = Field(..., description="Reaction ID (`umf_...`).") 82 message: str | None = Field( 83 default=None, description="ID of the message this reaction is attached to (`msg_...`)." 84 ) 85 payload: dict[str, Any] | None = Field( 86 default=None, 87 description='Structured data for the reaction. For `"emoji_reaction"` types, includes an `emoji` key with the Unicode emoji string.', 88 ) 89 updated_at: datetime | None = Field( 90 default=None, description="When the reaction was last modified (ISO 8601)." 91 ) 92 user: str | None = Field( 93 default=None, description="ID of the user who added the reaction (`usr_...`)." 94 ) 95 96 97class ReactionCreateResponse(BaseModel): 98 """ 99 Successful response 100 """ 101 102 data: ReactionCreateResponseData = Field(..., description="Reaction object that was created.") 103 104 105class AsyncReactionResource: 106 def __init__(self, http: HttpClient): 107 self._http = http 108 109 async def remove(self, message: str) -> None: 110 """ 111 Remove a reaction from a thread message 112 Removes the authenticated user's emoji reaction from the specified thread 113 message. The reaction is identified by the combination of the message ID and 114 the emoji; only the reaction belonging to the calling user is removed. 115 Returns 204 No Content on success. Returns 404 if no matching reaction 116 exists for the user and emoji on that message, or if the message itself 117 cannot be found. The authenticated user must have read access to the thread 118 containing the message. 119 120 Args: 121 message: Message ID (`msg_...`) of the thread message whose reaction should be removed. 122 123 Returns: 124 Empty response body. HTTP 204 No Content on success. 125 """ 126 await self._http.request(f"/api/v1/thread_messages/{message}/reactions", method="DELETE") 127 128 async def create(self, message: str, input: ReactionCreateInput) -> ReactionCreateResponse: 129 """ 130 Add a reaction to a thread message 131 Adds an emoji reaction to the specified thread message on behalf of the 132 authenticated user. If the user has already reacted to the message with the 133 same emoji, the request returns a 409 Conflict rather than creating a 134 duplicate. 135 The authenticated user must have read access to the thread containing the 136 message. If the thread belongs to a team, the user must be a member of 137 that team. 138 139 Args: 140 message: Message ID (`msg_...`) of the thread message whose reaction should be removed. 141 input: Request body. 142 input.emoji: Emoji character or shortcode to add as a reaction, e.g. `" "` or `":thumbsup:"`. 143 144 Returns: 145 Successful response 146 """ 147 return await self._http.request( 148 f"/api/v1/thread_messages/{message}/reactions", 149 method="POST", 150 body=input, 151 response_type=ReactionCreateResponse, 152 ) 153 154 155class AsyncThreadMessageResource: 156 def __init__(self, http: HttpClient): 157 self._http = http 158 self.reactions = AsyncReactionResource(http) 159 160 async def delete(self, message: str) -> None: 161 """ 162 Delete a thread message 163 Permanently removes the specified message from its thread. This action 164 cannot be undone. 165 A message may be deleted by its author, an admin of the org the message 166 belongs to, an admin of the team that owns the thread, or the agent that 167 sent it. Service-to-service callers with elevated (`all_powerful`) scope 168 may delete any message in a thread they can access. Returns 169 `403 Forbidden` when the caller is not permitted to delete the message. 170 171 Args: 172 message: ID of the message to delete (`msg_...`). 173 174 Returns: 175 Empty body. The server responds with HTTP 204 No Content on success. 176 """ 177 await self._http.request(f"/api/v1/thread_messages/{message}", method="DELETE") 178 179 async def get(self, message: str) -> ThreadMessage: 180 """ 181 Retrieve a message 182 Returns a single message by its globally unique message ID. The authenticated 183 viewer must be able to read the message and its thread. 184 The response includes the message's content, sender information, and any 185 attachments that were loaded at creation time. For admin-authenticated 186 requests, an additional `admin` field is returned containing raw metadata 187 and the associated trajectory data (LLM input/output messages) if one exists. 188 A trajectory belongs to the agent response it produced, so `admin.trajectory` 189 is only populated on the response message. On the triggering user message 190 the trajectory is omitted and `admin.response_message` links to the agent 191 response (where the trajectory is shown), when a response exists. 192 If the message is not found or is not visible to the caller, a 404 is 193 returned. 194 195 Args: 196 message: Globally unique message ID (`msg_...`). 197 198 Returns: 199 The requested message, including its content, sender, and attachments. 200 """ 201 return await self._http.request( 202 f"/api/v1/thread_messages/{message}", 203 response_type=ThreadMessage, 204 ) 205 206 async def replace(self, message: str, input: ThreadMessageReplaceInput) -> Message: 207 """ 208 Update a thread message 209 Edits an existing thread message and returns the updated message object. 210 A regular user may only edit messages they authored. Service-to-service 211 callers with elevated (`all_powerful`) scope may edit any accessible message 212 without an ownership check. Returns `403 Forbidden` when the caller does not 213 own the message. 214 215 Args: 216 message: ID of the message to update (`msg_...`). 217 input: Request body. 218 input.acl: Access control list for a private message (replace or patch grants). Only valid when the message is already `private`. Omit to leave unchanged. 219 input.content: Replacement text content for the message. Omit to leave the content unchanged. 220 input.metadata: Replacement key-value metadata. Keys beginning with `sys:` are reserved and stripped. 221 input.type: Replacement client-defined classification. Free-form string up to 64 characters; platform-reserved values such as `system` are rejected. 222 input.visibility: Create-time message visibility. Supplying the existing value is harmless, but changing between `default` and `private` returns 422. 223 224 Returns: 225 The updated message object. 226 """ 227 return await self._http.request( 228 f"/api/v1/thread_messages/{message}", 229 method="PUT", 230 body=input, 231 response_type=Message, 232 ) 233 234 async def replies( 235 self, 236 message: str, 237 *, 238 before_cursor: str | None = None, 239 after_cursor: str | None = None, 240 limit: int | None = None, 241 tree: bool | None = None, 242 ) -> PaginatedReplies: 243 """ 244 List replies to a thread message 245 Returns a cursor-paginated list of reply messages for the specified thread 246 message. By default only direct (first-level) replies are returned. Set 247 `tree` to `true` to retrieve the full nested reply tree in a flat list, 248 ordered by creation time ascending. 249 The authenticated user must have access to the thread that contains the 250 message. If the message belongs to a team-scoped thread, the viewer is 251 automatically scoped to that team before the query executes. 252 Use `before_cursor` and `after_cursor` together with `limit` to page 253 through large reply threads. The `has_more` field in the response 254 indicates whether additional pages exist. 255 256 Args: 257 message: ID of the thread message to fetch replies for (`msg_...`). 258 before_cursor: Opaque pagination cursor. Returns replies created before this point. Obtain from `before_cursor` in a previous response. 259 after_cursor: Opaque pagination cursor. Returns replies created after this point. Obtain from `after_cursor` in a previous response. 260 limit: Maximum number of replies to return per page. Defaults to 20. 261 tree: When `true`, returns all replies in the nested reply tree (flattened). When `false` or omitted, returns only direct replies to the message. 262 263 Returns: 264 Cursor-paginated list of reply messages for the requested thread message. 265 """ 266 query: dict[str, object] = {} 267 if before_cursor is not None: 268 query["before_cursor"] = before_cursor 269 if after_cursor is not None: 270 query["after_cursor"] = after_cursor 271 if limit is not None: 272 query["limit"] = limit 273 if tree is not None: 274 query["tree"] = tree 275 return await self._http.request( 276 f"/api/v1/thread_messages/{message}/replies", 277 query=query, 278 response_type=PaginatedReplies, 279 ) 280 281 282class ReactionResource: 283 def __init__(self, http: SyncHttpClient): 284 self._http = http 285 286 def remove(self, message: str) -> None: 287 """ 288 Remove a reaction from a thread message 289 Removes the authenticated user's emoji reaction from the specified thread 290 message. The reaction is identified by the combination of the message ID and 291 the emoji; only the reaction belonging to the calling user is removed. 292 Returns 204 No Content on success. Returns 404 if no matching reaction 293 exists for the user and emoji on that message, or if the message itself 294 cannot be found. The authenticated user must have read access to the thread 295 containing the message. 296 297 Args: 298 message: Message ID (`msg_...`) of the thread message whose reaction should be removed. 299 300 Returns: 301 Empty response body. HTTP 204 No Content on success. 302 """ 303 self._http.request(f"/api/v1/thread_messages/{message}/reactions", method="DELETE") 304 305 def create(self, message: str, input: ReactionCreateInput) -> ReactionCreateResponse: 306 """ 307 Add a reaction to a thread message 308 Adds an emoji reaction to the specified thread message on behalf of the 309 authenticated user. If the user has already reacted to the message with the 310 same emoji, the request returns a 409 Conflict rather than creating a 311 duplicate. 312 The authenticated user must have read access to the thread containing the 313 message. If the thread belongs to a team, the user must be a member of 314 that team. 315 316 Args: 317 message: Message ID (`msg_...`) of the thread message whose reaction should be removed. 318 input: Request body. 319 input.emoji: Emoji character or shortcode to add as a reaction, e.g. `" "` or `":thumbsup:"`. 320 321 Returns: 322 Successful response 323 """ 324 return self._http.request( 325 f"/api/v1/thread_messages/{message}/reactions", 326 method="POST", 327 body=input, 328 response_type=ReactionCreateResponse, 329 ) 330 331 332class ThreadMessageResource: 333 def __init__(self, http: SyncHttpClient): 334 self._http = http 335 self.reactions = ReactionResource(http) 336 337 def delete(self, message: str) -> None: 338 """ 339 Delete a thread message 340 Permanently removes the specified message from its thread. This action 341 cannot be undone. 342 A message may be deleted by its author, an admin of the org the message 343 belongs to, an admin of the team that owns the thread, or the agent that 344 sent it. Service-to-service callers with elevated (`all_powerful`) scope 345 may delete any message in a thread they can access. Returns 346 `403 Forbidden` when the caller is not permitted to delete the message. 347 348 Args: 349 message: ID of the message to delete (`msg_...`). 350 351 Returns: 352 Empty body. The server responds with HTTP 204 No Content on success. 353 """ 354 self._http.request(f"/api/v1/thread_messages/{message}", method="DELETE") 355 356 def get(self, message: str) -> ThreadMessage: 357 """ 358 Retrieve a message 359 Returns a single message by its globally unique message ID. The authenticated 360 viewer must be able to read the message and its thread. 361 The response includes the message's content, sender information, and any 362 attachments that were loaded at creation time. For admin-authenticated 363 requests, an additional `admin` field is returned containing raw metadata 364 and the associated trajectory data (LLM input/output messages) if one exists. 365 A trajectory belongs to the agent response it produced, so `admin.trajectory` 366 is only populated on the response message. On the triggering user message 367 the trajectory is omitted and `admin.response_message` links to the agent 368 response (where the trajectory is shown), when a response exists. 369 If the message is not found or is not visible to the caller, a 404 is 370 returned. 371 372 Args: 373 message: Globally unique message ID (`msg_...`). 374 375 Returns: 376 The requested message, including its content, sender, and attachments. 377 """ 378 return self._http.request(f"/api/v1/thread_messages/{message}", response_type=ThreadMessage) 379 380 def replace(self, message: str, input: ThreadMessageReplaceInput) -> Message: 381 """ 382 Update a thread message 383 Edits an existing thread message and returns the updated message object. 384 A regular user may only edit messages they authored. Service-to-service 385 callers with elevated (`all_powerful`) scope may edit any accessible message 386 without an ownership check. Returns `403 Forbidden` when the caller does not 387 own the message. 388 389 Args: 390 message: ID of the message to update (`msg_...`). 391 input: Request body. 392 input.acl: Access control list for a private message (replace or patch grants). Only valid when the message is already `private`. Omit to leave unchanged. 393 input.content: Replacement text content for the message. Omit to leave the content unchanged. 394 input.metadata: Replacement key-value metadata. Keys beginning with `sys:` are reserved and stripped. 395 input.type: Replacement client-defined classification. Free-form string up to 64 characters; platform-reserved values such as `system` are rejected. 396 input.visibility: Create-time message visibility. Supplying the existing value is harmless, but changing between `default` and `private` returns 422. 397 398 Returns: 399 The updated message object. 400 """ 401 return self._http.request( 402 f"/api/v1/thread_messages/{message}", 403 method="PUT", 404 body=input, 405 response_type=Message, 406 ) 407 408 def replies( 409 self, 410 message: str, 411 *, 412 before_cursor: str | None = None, 413 after_cursor: str | None = None, 414 limit: int | None = None, 415 tree: bool | None = None, 416 ) -> PaginatedReplies: 417 """ 418 List replies to a thread message 419 Returns a cursor-paginated list of reply messages for the specified thread 420 message. By default only direct (first-level) replies are returned. Set 421 `tree` to `true` to retrieve the full nested reply tree in a flat list, 422 ordered by creation time ascending. 423 The authenticated user must have access to the thread that contains the 424 message. If the message belongs to a team-scoped thread, the viewer is 425 automatically scoped to that team before the query executes. 426 Use `before_cursor` and `after_cursor` together with `limit` to page 427 through large reply threads. The `has_more` field in the response 428 indicates whether additional pages exist. 429 430 Args: 431 message: ID of the thread message to fetch replies for (`msg_...`). 432 before_cursor: Opaque pagination cursor. Returns replies created before this point. Obtain from `before_cursor` in a previous response. 433 after_cursor: Opaque pagination cursor. Returns replies created after this point. Obtain from `after_cursor` in a previous response. 434 limit: Maximum number of replies to return per page. Defaults to 20. 435 tree: When `true`, returns all replies in the nested reply tree (flattened). When `false` or omitted, returns only direct replies to the message. 436 437 Returns: 438 Cursor-paginated list of reply messages for the requested thread message. 439 """ 440 query: dict[str, object] = {} 441 if before_cursor is not None: 442 query["before_cursor"] = before_cursor 443 if after_cursor is not None: 444 query["after_cursor"] = after_cursor 445 if limit is not None: 446 query["limit"] = limit 447 if tree is not None: 448 query["tree"] = tree 449 return self._http.request( 450 f"/api/v1/thread_messages/{message}/replies", 451 query=query, 452 response_type=PaginatedReplies, 453 )
18class ReactionCreateInput(TypedDict): 19 "Add a reaction to a thread message" 20 21 emoji: str 22 'Emoji character or shortcode to add as a reaction, e.g. `" "` or `":thumbsup:"`.'
Add a reaction to a thread message
25class ThreadMessageReplaceInputAclAddItem(TypedDict, total=False): 26 actions: Required[list[str]] 27 'Array of action strings the principal is permitted to perform, e.g. `["read", "write"]`. Must contain at least one entry.' 28 principal: str | None 29 '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"`.' 30 principal_type: Required[str] 31 'The kind of principal receiving the grant. One of `"user"`, `"team"`, `"org"`, `"org_role"`, `"agent"`, or `"everyone"`.'
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".
34class ThreadMessageReplaceInputAclGrantsItem(TypedDict, total=False): 35 actions: Required[list[str]] 36 'Array of action strings the principal is permitted to perform, e.g. `["read", "write"]`. Must contain at least one entry.' 37 principal: str | None 38 '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"`.' 39 principal_type: Required[str] 40 'The kind of principal receiving the grant. One of `"user"`, `"team"`, `"org"`, `"org_role"`, `"agent"`, or `"everyone"`.'
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".
43class ThreadMessageReplaceInputAclRemoveItem(TypedDict, total=False): 44 principal: str | None 45 '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"`.' 46 principal_type: Required[str] 47 'The kind of principal to remove. One of `"user"`, `"team"`, `"org"`, `"org_role"`, `"agent"`, or `"everyone"`.'
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".
50class ThreadMessageReplaceInputAcl(TypedDict, total=False): 51 add: list[ThreadMessageReplaceInputAclAddItem] | None 52 "Patch mode: grants to add or merge into the existing list. Cannot be combined with `grants`." 53 grants: list[ThreadMessageReplaceInputAclGrantsItem] | None 54 "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`." 55 remove: list[ThreadMessageReplaceInputAclRemoveItem] | None 56 "Patch mode: principals whose grants should be removed from the existing list. Cannot be combined with `grants`."
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.
59class ThreadMessageReplaceInput(TypedDict, total=False): 60 "Update a thread message" 61 62 acl: ThreadMessageReplaceInputAcl | None 63 "Access control list for a private message (replace or patch grants). Only valid when the message is already `private`. Omit to leave unchanged." 64 content: str | None 65 "Replacement text content for the message. Omit to leave the content unchanged." 66 metadata: dict[str, Any] | None 67 "Replacement key-value metadata. Keys beginning with `sys:` are reserved and stripped." 68 type: str | None 69 "Replacement client-defined classification. Free-form string up to 64 characters; platform-reserved values such as `system` are rejected." 70 visibility: Literal["default", "private"] | None 71 "Create-time message visibility. Supplying the existing value is harmless, but changing between `default` and `private` returns 422."
Update a thread message
Access control list for a private message (replace or patch grants). Only valid when the message is already private. Omit to leave unchanged.
Replacement key-value metadata. Keys beginning with sys: are reserved and stripped.
74class ReactionCreateResponseData(BaseModel): 75 created_at: datetime | None = Field( 76 default=None, description="When the reaction was added (ISO 8601)." 77 ) 78 feedback_type: str | None = Field( 79 default=None, 80 description='Category of feedback. Currently `"emoji_reaction"` for emoji responses.', 81 ) 82 id: str = Field(..., description="Reaction ID (`umf_...`).") 83 message: str | None = Field( 84 default=None, description="ID of the message this reaction is attached to (`msg_...`)." 85 ) 86 payload: dict[str, Any] | None = Field( 87 default=None, 88 description='Structured data for the reaction. For `"emoji_reaction"` types, includes an `emoji` key with the Unicode emoji string.', 89 ) 90 updated_at: datetime | None = Field( 91 default=None, description="When the reaction was last modified (ISO 8601)." 92 ) 93 user: str | None = Field( 94 default=None, description="ID of the user who added the reaction (`usr_...`)." 95 )
!!! 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.
Category of feedback. Currently "emoji_reaction" for emoji responses.
98class ReactionCreateResponse(BaseModel): 99 """ 100 Successful response 101 """ 102 103 data: ReactionCreateResponseData = Field(..., description="Reaction object that was created.")
Successful response
106class AsyncReactionResource: 107 def __init__(self, http: HttpClient): 108 self._http = http 109 110 async def remove(self, message: str) -> None: 111 """ 112 Remove a reaction from a thread message 113 Removes the authenticated user's emoji reaction from the specified thread 114 message. The reaction is identified by the combination of the message ID and 115 the emoji; only the reaction belonging to the calling user is removed. 116 Returns 204 No Content on success. Returns 404 if no matching reaction 117 exists for the user and emoji on that message, or if the message itself 118 cannot be found. The authenticated user must have read access to the thread 119 containing the message. 120 121 Args: 122 message: Message ID (`msg_...`) of the thread message whose reaction should be removed. 123 124 Returns: 125 Empty response body. HTTP 204 No Content on success. 126 """ 127 await self._http.request(f"/api/v1/thread_messages/{message}/reactions", method="DELETE") 128 129 async def create(self, message: str, input: ReactionCreateInput) -> ReactionCreateResponse: 130 """ 131 Add a reaction to a thread message 132 Adds an emoji reaction to the specified thread message on behalf of the 133 authenticated user. If the user has already reacted to the message with the 134 same emoji, the request returns a 409 Conflict rather than creating a 135 duplicate. 136 The authenticated user must have read access to the thread containing the 137 message. If the thread belongs to a team, the user must be a member of 138 that team. 139 140 Args: 141 message: Message ID (`msg_...`) of the thread message whose reaction should be removed. 142 input: Request body. 143 input.emoji: Emoji character or shortcode to add as a reaction, e.g. `" "` or `":thumbsup:"`. 144 145 Returns: 146 Successful response 147 """ 148 return await self._http.request( 149 f"/api/v1/thread_messages/{message}/reactions", 150 method="POST", 151 body=input, 152 response_type=ReactionCreateResponse, 153 )
110 async def remove(self, message: str) -> None: 111 """ 112 Remove a reaction from a thread message 113 Removes the authenticated user's emoji reaction from the specified thread 114 message. The reaction is identified by the combination of the message ID and 115 the emoji; only the reaction belonging to the calling user is removed. 116 Returns 204 No Content on success. Returns 404 if no matching reaction 117 exists for the user and emoji on that message, or if the message itself 118 cannot be found. The authenticated user must have read access to the thread 119 containing the message. 120 121 Args: 122 message: Message ID (`msg_...`) of the thread message whose reaction should be removed. 123 124 Returns: 125 Empty response body. HTTP 204 No Content on success. 126 """ 127 await self._http.request(f"/api/v1/thread_messages/{message}/reactions", method="DELETE")
Remove a reaction from a thread message Removes the authenticated user's emoji reaction from the specified thread message. The reaction is identified by the combination of the message ID and the emoji; only the reaction belonging to the calling user is removed. Returns 204 No Content on success. Returns 404 if no matching reaction exists for the user and emoji on that message, or if the message itself cannot be found. The authenticated user must have read access to the thread containing the message.
Arguments:
- message: Message ID (
msg_...) of the thread message whose reaction should be removed.
Returns:
Empty response body. HTTP 204 No Content on success.
129 async def create(self, message: str, input: ReactionCreateInput) -> ReactionCreateResponse: 130 """ 131 Add a reaction to a thread message 132 Adds an emoji reaction to the specified thread message on behalf of the 133 authenticated user. If the user has already reacted to the message with the 134 same emoji, the request returns a 409 Conflict rather than creating a 135 duplicate. 136 The authenticated user must have read access to the thread containing the 137 message. If the thread belongs to a team, the user must be a member of 138 that team. 139 140 Args: 141 message: Message ID (`msg_...`) of the thread message whose reaction should be removed. 142 input: Request body. 143 input.emoji: Emoji character or shortcode to add as a reaction, e.g. `" "` or `":thumbsup:"`. 144 145 Returns: 146 Successful response 147 """ 148 return await self._http.request( 149 f"/api/v1/thread_messages/{message}/reactions", 150 method="POST", 151 body=input, 152 response_type=ReactionCreateResponse, 153 )
Add a reaction to a thread message Adds an emoji reaction to the specified thread message on behalf of the authenticated user. If the user has already reacted to the message with the same emoji, the request returns a 409 Conflict rather than creating a duplicate. The authenticated user must have read access to the thread containing the message. If the thread belongs to a team, the user must be a member of that team.
Arguments:
- message: Message ID (
msg_...) of the thread message whose reaction should be removed. - input: Request body.
- input.emoji: Emoji character or shortcode to add as a reaction, e.g.
" "or":thumbsup:".
Returns:
Successful response
156class AsyncThreadMessageResource: 157 def __init__(self, http: HttpClient): 158 self._http = http 159 self.reactions = AsyncReactionResource(http) 160 161 async def delete(self, message: str) -> None: 162 """ 163 Delete a thread message 164 Permanently removes the specified message from its thread. This action 165 cannot be undone. 166 A message may be deleted by its author, an admin of the org the message 167 belongs to, an admin of the team that owns the thread, or the agent that 168 sent it. Service-to-service callers with elevated (`all_powerful`) scope 169 may delete any message in a thread they can access. Returns 170 `403 Forbidden` when the caller is not permitted to delete the message. 171 172 Args: 173 message: ID of the message to delete (`msg_...`). 174 175 Returns: 176 Empty body. The server responds with HTTP 204 No Content on success. 177 """ 178 await self._http.request(f"/api/v1/thread_messages/{message}", method="DELETE") 179 180 async def get(self, message: str) -> ThreadMessage: 181 """ 182 Retrieve a message 183 Returns a single message by its globally unique message ID. The authenticated 184 viewer must be able to read the message and its thread. 185 The response includes the message's content, sender information, and any 186 attachments that were loaded at creation time. For admin-authenticated 187 requests, an additional `admin` field is returned containing raw metadata 188 and the associated trajectory data (LLM input/output messages) if one exists. 189 A trajectory belongs to the agent response it produced, so `admin.trajectory` 190 is only populated on the response message. On the triggering user message 191 the trajectory is omitted and `admin.response_message` links to the agent 192 response (where the trajectory is shown), when a response exists. 193 If the message is not found or is not visible to the caller, a 404 is 194 returned. 195 196 Args: 197 message: Globally unique message ID (`msg_...`). 198 199 Returns: 200 The requested message, including its content, sender, and attachments. 201 """ 202 return await self._http.request( 203 f"/api/v1/thread_messages/{message}", 204 response_type=ThreadMessage, 205 ) 206 207 async def replace(self, message: str, input: ThreadMessageReplaceInput) -> Message: 208 """ 209 Update a thread message 210 Edits an existing thread message and returns the updated message object. 211 A regular user may only edit messages they authored. Service-to-service 212 callers with elevated (`all_powerful`) scope may edit any accessible message 213 without an ownership check. Returns `403 Forbidden` when the caller does not 214 own the message. 215 216 Args: 217 message: ID of the message to update (`msg_...`). 218 input: Request body. 219 input.acl: Access control list for a private message (replace or patch grants). Only valid when the message is already `private`. Omit to leave unchanged. 220 input.content: Replacement text content for the message. Omit to leave the content unchanged. 221 input.metadata: Replacement key-value metadata. Keys beginning with `sys:` are reserved and stripped. 222 input.type: Replacement client-defined classification. Free-form string up to 64 characters; platform-reserved values such as `system` are rejected. 223 input.visibility: Create-time message visibility. Supplying the existing value is harmless, but changing between `default` and `private` returns 422. 224 225 Returns: 226 The updated message object. 227 """ 228 return await self._http.request( 229 f"/api/v1/thread_messages/{message}", 230 method="PUT", 231 body=input, 232 response_type=Message, 233 ) 234 235 async def replies( 236 self, 237 message: str, 238 *, 239 before_cursor: str | None = None, 240 after_cursor: str | None = None, 241 limit: int | None = None, 242 tree: bool | None = None, 243 ) -> PaginatedReplies: 244 """ 245 List replies to a thread message 246 Returns a cursor-paginated list of reply messages for the specified thread 247 message. By default only direct (first-level) replies are returned. Set 248 `tree` to `true` to retrieve the full nested reply tree in a flat list, 249 ordered by creation time ascending. 250 The authenticated user must have access to the thread that contains the 251 message. If the message belongs to a team-scoped thread, the viewer is 252 automatically scoped to that team before the query executes. 253 Use `before_cursor` and `after_cursor` together with `limit` to page 254 through large reply threads. The `has_more` field in the response 255 indicates whether additional pages exist. 256 257 Args: 258 message: ID of the thread message to fetch replies for (`msg_...`). 259 before_cursor: Opaque pagination cursor. Returns replies created before this point. Obtain from `before_cursor` in a previous response. 260 after_cursor: Opaque pagination cursor. Returns replies created after this point. Obtain from `after_cursor` in a previous response. 261 limit: Maximum number of replies to return per page. Defaults to 20. 262 tree: When `true`, returns all replies in the nested reply tree (flattened). When `false` or omitted, returns only direct replies to the message. 263 264 Returns: 265 Cursor-paginated list of reply messages for the requested thread message. 266 """ 267 query: dict[str, object] = {} 268 if before_cursor is not None: 269 query["before_cursor"] = before_cursor 270 if after_cursor is not None: 271 query["after_cursor"] = after_cursor 272 if limit is not None: 273 query["limit"] = limit 274 if tree is not None: 275 query["tree"] = tree 276 return await self._http.request( 277 f"/api/v1/thread_messages/{message}/replies", 278 query=query, 279 response_type=PaginatedReplies, 280 )
161 async def delete(self, message: str) -> None: 162 """ 163 Delete a thread message 164 Permanently removes the specified message from its thread. This action 165 cannot be undone. 166 A message may be deleted by its author, an admin of the org the message 167 belongs to, an admin of the team that owns the thread, or the agent that 168 sent it. Service-to-service callers with elevated (`all_powerful`) scope 169 may delete any message in a thread they can access. Returns 170 `403 Forbidden` when the caller is not permitted to delete the message. 171 172 Args: 173 message: ID of the message to delete (`msg_...`). 174 175 Returns: 176 Empty body. The server responds with HTTP 204 No Content on success. 177 """ 178 await self._http.request(f"/api/v1/thread_messages/{message}", method="DELETE")
Delete a thread message
Permanently removes the specified message from its thread. This action
cannot be undone.
A message may be deleted by its author, an admin of the org the message
belongs to, an admin of the team that owns the thread, or the agent that
sent it. Service-to-service callers with elevated (all_powerful) scope
may delete any message in a thread they can access. Returns
403 Forbidden when the caller is not permitted to delete the message.
Arguments:
- message: ID of the message to delete (
msg_...).
Returns:
Empty body. The server responds with HTTP 204 No Content on success.
180 async def get(self, message: str) -> ThreadMessage: 181 """ 182 Retrieve a message 183 Returns a single message by its globally unique message ID. The authenticated 184 viewer must be able to read the message and its thread. 185 The response includes the message's content, sender information, and any 186 attachments that were loaded at creation time. For admin-authenticated 187 requests, an additional `admin` field is returned containing raw metadata 188 and the associated trajectory data (LLM input/output messages) if one exists. 189 A trajectory belongs to the agent response it produced, so `admin.trajectory` 190 is only populated on the response message. On the triggering user message 191 the trajectory is omitted and `admin.response_message` links to the agent 192 response (where the trajectory is shown), when a response exists. 193 If the message is not found or is not visible to the caller, a 404 is 194 returned. 195 196 Args: 197 message: Globally unique message ID (`msg_...`). 198 199 Returns: 200 The requested message, including its content, sender, and attachments. 201 """ 202 return await self._http.request( 203 f"/api/v1/thread_messages/{message}", 204 response_type=ThreadMessage, 205 )
Retrieve a message
Returns a single message by its globally unique message ID. The authenticated
viewer must be able to read the message and its thread.
The response includes the message's content, sender information, and any
attachments that were loaded at creation time. For admin-authenticated
requests, an additional admin field is returned containing raw metadata
and the associated trajectory data (LLM input/output messages) if one exists.
A trajectory belongs to the agent response it produced, so admin.trajectory
is only populated on the response message. On the triggering user message
the trajectory is omitted and admin.response_message links to the agent
response (where the trajectory is shown), when a response exists.
If the message is not found or is not visible to the caller, a 404 is
returned.
Arguments:
- message: Globally unique message ID (
msg_...).
Returns:
The requested message, including its content, sender, and attachments.
207 async def replace(self, message: str, input: ThreadMessageReplaceInput) -> Message: 208 """ 209 Update a thread message 210 Edits an existing thread message and returns the updated message object. 211 A regular user may only edit messages they authored. Service-to-service 212 callers with elevated (`all_powerful`) scope may edit any accessible message 213 without an ownership check. Returns `403 Forbidden` when the caller does not 214 own the message. 215 216 Args: 217 message: ID of the message to update (`msg_...`). 218 input: Request body. 219 input.acl: Access control list for a private message (replace or patch grants). Only valid when the message is already `private`. Omit to leave unchanged. 220 input.content: Replacement text content for the message. Omit to leave the content unchanged. 221 input.metadata: Replacement key-value metadata. Keys beginning with `sys:` are reserved and stripped. 222 input.type: Replacement client-defined classification. Free-form string up to 64 characters; platform-reserved values such as `system` are rejected. 223 input.visibility: Create-time message visibility. Supplying the existing value is harmless, but changing between `default` and `private` returns 422. 224 225 Returns: 226 The updated message object. 227 """ 228 return await self._http.request( 229 f"/api/v1/thread_messages/{message}", 230 method="PUT", 231 body=input, 232 response_type=Message, 233 )
Update a thread message
Edits an existing thread message and returns the updated message object.
A regular user may only edit messages they authored. Service-to-service
callers with elevated (all_powerful) scope may edit any accessible message
without an ownership check. Returns 403 Forbidden when the caller does not
own the message.
Arguments:
- message: ID of the message to update (
msg_...). - input: Request body.
- input.acl: Access control list for a private message (replace or patch grants). Only valid when the message is already
private. Omit to leave unchanged. - input.content: Replacement text content for the message. Omit to leave the content unchanged.
- input.metadata: Replacement key-value metadata. Keys beginning with
sys:are reserved and stripped. - input.type: Replacement client-defined classification. Free-form string up to 64 characters; platform-reserved values such as
systemare rejected. - input.visibility: Create-time message visibility. Supplying the existing value is harmless, but changing between
defaultandprivatereturns 422.
Returns:
The updated message object.
235 async def replies( 236 self, 237 message: str, 238 *, 239 before_cursor: str | None = None, 240 after_cursor: str | None = None, 241 limit: int | None = None, 242 tree: bool | None = None, 243 ) -> PaginatedReplies: 244 """ 245 List replies to a thread message 246 Returns a cursor-paginated list of reply messages for the specified thread 247 message. By default only direct (first-level) replies are returned. Set 248 `tree` to `true` to retrieve the full nested reply tree in a flat list, 249 ordered by creation time ascending. 250 The authenticated user must have access to the thread that contains the 251 message. If the message belongs to a team-scoped thread, the viewer is 252 automatically scoped to that team before the query executes. 253 Use `before_cursor` and `after_cursor` together with `limit` to page 254 through large reply threads. The `has_more` field in the response 255 indicates whether additional pages exist. 256 257 Args: 258 message: ID of the thread message to fetch replies for (`msg_...`). 259 before_cursor: Opaque pagination cursor. Returns replies created before this point. Obtain from `before_cursor` in a previous response. 260 after_cursor: Opaque pagination cursor. Returns replies created after this point. Obtain from `after_cursor` in a previous response. 261 limit: Maximum number of replies to return per page. Defaults to 20. 262 tree: When `true`, returns all replies in the nested reply tree (flattened). When `false` or omitted, returns only direct replies to the message. 263 264 Returns: 265 Cursor-paginated list of reply messages for the requested thread message. 266 """ 267 query: dict[str, object] = {} 268 if before_cursor is not None: 269 query["before_cursor"] = before_cursor 270 if after_cursor is not None: 271 query["after_cursor"] = after_cursor 272 if limit is not None: 273 query["limit"] = limit 274 if tree is not None: 275 query["tree"] = tree 276 return await self._http.request( 277 f"/api/v1/thread_messages/{message}/replies", 278 query=query, 279 response_type=PaginatedReplies, 280 )
List replies to a thread message
Returns a cursor-paginated list of reply messages for the specified thread
message. By default only direct (first-level) replies are returned. Set
tree to true to retrieve the full nested reply tree in a flat list,
ordered by creation time ascending.
The authenticated user must have access to the thread that contains the
message. If the message belongs to a team-scoped thread, the viewer is
automatically scoped to that team before the query executes.
Use before_cursor and after_cursor together with limit to page
through large reply threads. The has_more field in the response
indicates whether additional pages exist.
Arguments:
- message: ID of the thread message to fetch replies for (
msg_...). - before_cursor: Opaque pagination cursor. Returns replies created before this point. Obtain from
before_cursorin a previous response. - after_cursor: Opaque pagination cursor. Returns replies created after this point. Obtain from
after_cursorin a previous response. - limit: Maximum number of replies to return per page. Defaults to 20.
- tree: When
true, returns all replies in the nested reply tree (flattened). Whenfalseor omitted, returns only direct replies to the message.
Returns:
Cursor-paginated list of reply messages for the requested thread message.
283class ReactionResource: 284 def __init__(self, http: SyncHttpClient): 285 self._http = http 286 287 def remove(self, message: str) -> None: 288 """ 289 Remove a reaction from a thread message 290 Removes the authenticated user's emoji reaction from the specified thread 291 message. The reaction is identified by the combination of the message ID and 292 the emoji; only the reaction belonging to the calling user is removed. 293 Returns 204 No Content on success. Returns 404 if no matching reaction 294 exists for the user and emoji on that message, or if the message itself 295 cannot be found. The authenticated user must have read access to the thread 296 containing the message. 297 298 Args: 299 message: Message ID (`msg_...`) of the thread message whose reaction should be removed. 300 301 Returns: 302 Empty response body. HTTP 204 No Content on success. 303 """ 304 self._http.request(f"/api/v1/thread_messages/{message}/reactions", method="DELETE") 305 306 def create(self, message: str, input: ReactionCreateInput) -> ReactionCreateResponse: 307 """ 308 Add a reaction to a thread message 309 Adds an emoji reaction to the specified thread message on behalf of the 310 authenticated user. If the user has already reacted to the message with the 311 same emoji, the request returns a 409 Conflict rather than creating a 312 duplicate. 313 The authenticated user must have read access to the thread containing the 314 message. If the thread belongs to a team, the user must be a member of 315 that team. 316 317 Args: 318 message: Message ID (`msg_...`) of the thread message whose reaction should be removed. 319 input: Request body. 320 input.emoji: Emoji character or shortcode to add as a reaction, e.g. `" "` or `":thumbsup:"`. 321 322 Returns: 323 Successful response 324 """ 325 return self._http.request( 326 f"/api/v1/thread_messages/{message}/reactions", 327 method="POST", 328 body=input, 329 response_type=ReactionCreateResponse, 330 )
287 def remove(self, message: str) -> None: 288 """ 289 Remove a reaction from a thread message 290 Removes the authenticated user's emoji reaction from the specified thread 291 message. The reaction is identified by the combination of the message ID and 292 the emoji; only the reaction belonging to the calling user is removed. 293 Returns 204 No Content on success. Returns 404 if no matching reaction 294 exists for the user and emoji on that message, or if the message itself 295 cannot be found. The authenticated user must have read access to the thread 296 containing the message. 297 298 Args: 299 message: Message ID (`msg_...`) of the thread message whose reaction should be removed. 300 301 Returns: 302 Empty response body. HTTP 204 No Content on success. 303 """ 304 self._http.request(f"/api/v1/thread_messages/{message}/reactions", method="DELETE")
Remove a reaction from a thread message Removes the authenticated user's emoji reaction from the specified thread message. The reaction is identified by the combination of the message ID and the emoji; only the reaction belonging to the calling user is removed. Returns 204 No Content on success. Returns 404 if no matching reaction exists for the user and emoji on that message, or if the message itself cannot be found. The authenticated user must have read access to the thread containing the message.
Arguments:
- message: Message ID (
msg_...) of the thread message whose reaction should be removed.
Returns:
Empty response body. HTTP 204 No Content on success.
306 def create(self, message: str, input: ReactionCreateInput) -> ReactionCreateResponse: 307 """ 308 Add a reaction to a thread message 309 Adds an emoji reaction to the specified thread message on behalf of the 310 authenticated user. If the user has already reacted to the message with the 311 same emoji, the request returns a 409 Conflict rather than creating a 312 duplicate. 313 The authenticated user must have read access to the thread containing the 314 message. If the thread belongs to a team, the user must be a member of 315 that team. 316 317 Args: 318 message: Message ID (`msg_...`) of the thread message whose reaction should be removed. 319 input: Request body. 320 input.emoji: Emoji character or shortcode to add as a reaction, e.g. `" "` or `":thumbsup:"`. 321 322 Returns: 323 Successful response 324 """ 325 return self._http.request( 326 f"/api/v1/thread_messages/{message}/reactions", 327 method="POST", 328 body=input, 329 response_type=ReactionCreateResponse, 330 )
Add a reaction to a thread message Adds an emoji reaction to the specified thread message on behalf of the authenticated user. If the user has already reacted to the message with the same emoji, the request returns a 409 Conflict rather than creating a duplicate. The authenticated user must have read access to the thread containing the message. If the thread belongs to a team, the user must be a member of that team.
Arguments:
- message: Message ID (
msg_...) of the thread message whose reaction should be removed. - input: Request body.
- input.emoji: Emoji character or shortcode to add as a reaction, e.g.
" "or":thumbsup:".
Returns:
Successful response
333class ThreadMessageResource: 334 def __init__(self, http: SyncHttpClient): 335 self._http = http 336 self.reactions = ReactionResource(http) 337 338 def delete(self, message: str) -> None: 339 """ 340 Delete a thread message 341 Permanently removes the specified message from its thread. This action 342 cannot be undone. 343 A message may be deleted by its author, an admin of the org the message 344 belongs to, an admin of the team that owns the thread, or the agent that 345 sent it. Service-to-service callers with elevated (`all_powerful`) scope 346 may delete any message in a thread they can access. Returns 347 `403 Forbidden` when the caller is not permitted to delete the message. 348 349 Args: 350 message: ID of the message to delete (`msg_...`). 351 352 Returns: 353 Empty body. The server responds with HTTP 204 No Content on success. 354 """ 355 self._http.request(f"/api/v1/thread_messages/{message}", method="DELETE") 356 357 def get(self, message: str) -> ThreadMessage: 358 """ 359 Retrieve a message 360 Returns a single message by its globally unique message ID. The authenticated 361 viewer must be able to read the message and its thread. 362 The response includes the message's content, sender information, and any 363 attachments that were loaded at creation time. For admin-authenticated 364 requests, an additional `admin` field is returned containing raw metadata 365 and the associated trajectory data (LLM input/output messages) if one exists. 366 A trajectory belongs to the agent response it produced, so `admin.trajectory` 367 is only populated on the response message. On the triggering user message 368 the trajectory is omitted and `admin.response_message` links to the agent 369 response (where the trajectory is shown), when a response exists. 370 If the message is not found or is not visible to the caller, a 404 is 371 returned. 372 373 Args: 374 message: Globally unique message ID (`msg_...`). 375 376 Returns: 377 The requested message, including its content, sender, and attachments. 378 """ 379 return self._http.request(f"/api/v1/thread_messages/{message}", response_type=ThreadMessage) 380 381 def replace(self, message: str, input: ThreadMessageReplaceInput) -> Message: 382 """ 383 Update a thread message 384 Edits an existing thread message and returns the updated message object. 385 A regular user may only edit messages they authored. Service-to-service 386 callers with elevated (`all_powerful`) scope may edit any accessible message 387 without an ownership check. Returns `403 Forbidden` when the caller does not 388 own the message. 389 390 Args: 391 message: ID of the message to update (`msg_...`). 392 input: Request body. 393 input.acl: Access control list for a private message (replace or patch grants). Only valid when the message is already `private`. Omit to leave unchanged. 394 input.content: Replacement text content for the message. Omit to leave the content unchanged. 395 input.metadata: Replacement key-value metadata. Keys beginning with `sys:` are reserved and stripped. 396 input.type: Replacement client-defined classification. Free-form string up to 64 characters; platform-reserved values such as `system` are rejected. 397 input.visibility: Create-time message visibility. Supplying the existing value is harmless, but changing between `default` and `private` returns 422. 398 399 Returns: 400 The updated message object. 401 """ 402 return self._http.request( 403 f"/api/v1/thread_messages/{message}", 404 method="PUT", 405 body=input, 406 response_type=Message, 407 ) 408 409 def replies( 410 self, 411 message: str, 412 *, 413 before_cursor: str | None = None, 414 after_cursor: str | None = None, 415 limit: int | None = None, 416 tree: bool | None = None, 417 ) -> PaginatedReplies: 418 """ 419 List replies to a thread message 420 Returns a cursor-paginated list of reply messages for the specified thread 421 message. By default only direct (first-level) replies are returned. Set 422 `tree` to `true` to retrieve the full nested reply tree in a flat list, 423 ordered by creation time ascending. 424 The authenticated user must have access to the thread that contains the 425 message. If the message belongs to a team-scoped thread, the viewer is 426 automatically scoped to that team before the query executes. 427 Use `before_cursor` and `after_cursor` together with `limit` to page 428 through large reply threads. The `has_more` field in the response 429 indicates whether additional pages exist. 430 431 Args: 432 message: ID of the thread message to fetch replies for (`msg_...`). 433 before_cursor: Opaque pagination cursor. Returns replies created before this point. Obtain from `before_cursor` in a previous response. 434 after_cursor: Opaque pagination cursor. Returns replies created after this point. Obtain from `after_cursor` in a previous response. 435 limit: Maximum number of replies to return per page. Defaults to 20. 436 tree: When `true`, returns all replies in the nested reply tree (flattened). When `false` or omitted, returns only direct replies to the message. 437 438 Returns: 439 Cursor-paginated list of reply messages for the requested thread message. 440 """ 441 query: dict[str, object] = {} 442 if before_cursor is not None: 443 query["before_cursor"] = before_cursor 444 if after_cursor is not None: 445 query["after_cursor"] = after_cursor 446 if limit is not None: 447 query["limit"] = limit 448 if tree is not None: 449 query["tree"] = tree 450 return self._http.request( 451 f"/api/v1/thread_messages/{message}/replies", 452 query=query, 453 response_type=PaginatedReplies, 454 )
338 def delete(self, message: str) -> None: 339 """ 340 Delete a thread message 341 Permanently removes the specified message from its thread. This action 342 cannot be undone. 343 A message may be deleted by its author, an admin of the org the message 344 belongs to, an admin of the team that owns the thread, or the agent that 345 sent it. Service-to-service callers with elevated (`all_powerful`) scope 346 may delete any message in a thread they can access. Returns 347 `403 Forbidden` when the caller is not permitted to delete the message. 348 349 Args: 350 message: ID of the message to delete (`msg_...`). 351 352 Returns: 353 Empty body. The server responds with HTTP 204 No Content on success. 354 """ 355 self._http.request(f"/api/v1/thread_messages/{message}", method="DELETE")
Delete a thread message
Permanently removes the specified message from its thread. This action
cannot be undone.
A message may be deleted by its author, an admin of the org the message
belongs to, an admin of the team that owns the thread, or the agent that
sent it. Service-to-service callers with elevated (all_powerful) scope
may delete any message in a thread they can access. Returns
403 Forbidden when the caller is not permitted to delete the message.
Arguments:
- message: ID of the message to delete (
msg_...).
Returns:
Empty body. The server responds with HTTP 204 No Content on success.
357 def get(self, message: str) -> ThreadMessage: 358 """ 359 Retrieve a message 360 Returns a single message by its globally unique message ID. The authenticated 361 viewer must be able to read the message and its thread. 362 The response includes the message's content, sender information, and any 363 attachments that were loaded at creation time. For admin-authenticated 364 requests, an additional `admin` field is returned containing raw metadata 365 and the associated trajectory data (LLM input/output messages) if one exists. 366 A trajectory belongs to the agent response it produced, so `admin.trajectory` 367 is only populated on the response message. On the triggering user message 368 the trajectory is omitted and `admin.response_message` links to the agent 369 response (where the trajectory is shown), when a response exists. 370 If the message is not found or is not visible to the caller, a 404 is 371 returned. 372 373 Args: 374 message: Globally unique message ID (`msg_...`). 375 376 Returns: 377 The requested message, including its content, sender, and attachments. 378 """ 379 return self._http.request(f"/api/v1/thread_messages/{message}", response_type=ThreadMessage)
Retrieve a message
Returns a single message by its globally unique message ID. The authenticated
viewer must be able to read the message and its thread.
The response includes the message's content, sender information, and any
attachments that were loaded at creation time. For admin-authenticated
requests, an additional admin field is returned containing raw metadata
and the associated trajectory data (LLM input/output messages) if one exists.
A trajectory belongs to the agent response it produced, so admin.trajectory
is only populated on the response message. On the triggering user message
the trajectory is omitted and admin.response_message links to the agent
response (where the trajectory is shown), when a response exists.
If the message is not found or is not visible to the caller, a 404 is
returned.
Arguments:
- message: Globally unique message ID (
msg_...).
Returns:
The requested message, including its content, sender, and attachments.
381 def replace(self, message: str, input: ThreadMessageReplaceInput) -> Message: 382 """ 383 Update a thread message 384 Edits an existing thread message and returns the updated message object. 385 A regular user may only edit messages they authored. Service-to-service 386 callers with elevated (`all_powerful`) scope may edit any accessible message 387 without an ownership check. Returns `403 Forbidden` when the caller does not 388 own the message. 389 390 Args: 391 message: ID of the message to update (`msg_...`). 392 input: Request body. 393 input.acl: Access control list for a private message (replace or patch grants). Only valid when the message is already `private`. Omit to leave unchanged. 394 input.content: Replacement text content for the message. Omit to leave the content unchanged. 395 input.metadata: Replacement key-value metadata. Keys beginning with `sys:` are reserved and stripped. 396 input.type: Replacement client-defined classification. Free-form string up to 64 characters; platform-reserved values such as `system` are rejected. 397 input.visibility: Create-time message visibility. Supplying the existing value is harmless, but changing between `default` and `private` returns 422. 398 399 Returns: 400 The updated message object. 401 """ 402 return self._http.request( 403 f"/api/v1/thread_messages/{message}", 404 method="PUT", 405 body=input, 406 response_type=Message, 407 )
Update a thread message
Edits an existing thread message and returns the updated message object.
A regular user may only edit messages they authored. Service-to-service
callers with elevated (all_powerful) scope may edit any accessible message
without an ownership check. Returns 403 Forbidden when the caller does not
own the message.
Arguments:
- message: ID of the message to update (
msg_...). - input: Request body.
- input.acl: Access control list for a private message (replace or patch grants). Only valid when the message is already
private. Omit to leave unchanged. - input.content: Replacement text content for the message. Omit to leave the content unchanged.
- input.metadata: Replacement key-value metadata. Keys beginning with
sys:are reserved and stripped. - input.type: Replacement client-defined classification. Free-form string up to 64 characters; platform-reserved values such as
systemare rejected. - input.visibility: Create-time message visibility. Supplying the existing value is harmless, but changing between
defaultandprivatereturns 422.
Returns:
The updated message object.
409 def replies( 410 self, 411 message: str, 412 *, 413 before_cursor: str | None = None, 414 after_cursor: str | None = None, 415 limit: int | None = None, 416 tree: bool | None = None, 417 ) -> PaginatedReplies: 418 """ 419 List replies to a thread message 420 Returns a cursor-paginated list of reply messages for the specified thread 421 message. By default only direct (first-level) replies are returned. Set 422 `tree` to `true` to retrieve the full nested reply tree in a flat list, 423 ordered by creation time ascending. 424 The authenticated user must have access to the thread that contains the 425 message. If the message belongs to a team-scoped thread, the viewer is 426 automatically scoped to that team before the query executes. 427 Use `before_cursor` and `after_cursor` together with `limit` to page 428 through large reply threads. The `has_more` field in the response 429 indicates whether additional pages exist. 430 431 Args: 432 message: ID of the thread message to fetch replies for (`msg_...`). 433 before_cursor: Opaque pagination cursor. Returns replies created before this point. Obtain from `before_cursor` in a previous response. 434 after_cursor: Opaque pagination cursor. Returns replies created after this point. Obtain from `after_cursor` in a previous response. 435 limit: Maximum number of replies to return per page. Defaults to 20. 436 tree: When `true`, returns all replies in the nested reply tree (flattened). When `false` or omitted, returns only direct replies to the message. 437 438 Returns: 439 Cursor-paginated list of reply messages for the requested thread message. 440 """ 441 query: dict[str, object] = {} 442 if before_cursor is not None: 443 query["before_cursor"] = before_cursor 444 if after_cursor is not None: 445 query["after_cursor"] = after_cursor 446 if limit is not None: 447 query["limit"] = limit 448 if tree is not None: 449 query["tree"] = tree 450 return self._http.request( 451 f"/api/v1/thread_messages/{message}/replies", 452 query=query, 453 response_type=PaginatedReplies, 454 )
List replies to a thread message
Returns a cursor-paginated list of reply messages for the specified thread
message. By default only direct (first-level) replies are returned. Set
tree to true to retrieve the full nested reply tree in a flat list,
ordered by creation time ascending.
The authenticated user must have access to the thread that contains the
message. If the message belongs to a team-scoped thread, the viewer is
automatically scoped to that team before the query executes.
Use before_cursor and after_cursor together with limit to page
through large reply threads. The has_more field in the response
indicates whether additional pages exist.
Arguments:
- message: ID of the thread message to fetch replies for (
msg_...). - before_cursor: Opaque pagination cursor. Returns replies created before this point. Obtain from
before_cursorin a previous response. - after_cursor: Opaque pagination cursor. Returns replies created after this point. Obtain from
after_cursorin a previous response. - limit: Maximum number of replies to return per page. Defaults to 20.
- tree: When
true, returns all replies in the nested reply tree (flattened). Whenfalseor omitted, returns only direct replies to the message.
Returns:
Cursor-paginated list of reply messages for the requested thread message.