roboto.ai.agent_thread
Submodules
Package Contents
AGENT_CONTENT_MODEL_BY_TYPE
The model class for each JSON-serialized content type, keyed by discriminator.
Excludes AgentContentType.TEXT, whose payload is persisted as raw text rather than a serialized model. Every other member of AgentContent carries a content_type discriminator and round-trips through model_dump_json / model_validate_json; driving both serialization directions off this one map keeps them symmetric, so a member added to the union without a home here fails loudly instead of being silently dropped on write or reconstructed without its payload on read.
AdminUpdateFeedbackRequest
Bases: pydantic.BaseModel
Triage fields editable by Roboto admins.
Fields omitted from the request (NotSet) are left unchanged. Fields explicitly set to None clear the column back to NULL. Fields set to a value overwrite the column.
Setting resolved to True additionally stamps resolved_at and resolved_by server-side; setting it back to False clears them.
Parameters
data AnyAttributes
AdminUpdateFeedbackRequest.admin_label
AdminUpdateFeedbackRequest.admin_note
AdminUpdateFeedbackRequest.model_config
model_config #Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
AdminUpdateFeedbackRequest.resolved
AgentClientContextEntry
Bases: pydantic.BaseModel
The caller’s attached viewing context, carried on their own message.
Replaces a <ctx>{json}</ctx> marker persisted as a separate ROBOTO-role message. That shape made every consumer regex a JSON blob back out of prose it had serialized itself – four parsers across two languages – and relied on the ROBOTO role to keep the marker out of the chat view. It also put the context on a non-USER message, which the compression deletion pass collapses wholesale inside a resolved task’s interior, so the context silently disappeared from compressed history.
As a block on the user’s own message it is a typed field, invisible to text renderers (no text field), and safe from that collapse – USER turns are never dropped.
Parameters
data AnyAttributes
AgentClientContextEntry.content_type
AgentClientContextEntry.context
What the caller had open: attached datasets, files, and visualizer state.
AgentCompressionFillerContent
Bases: pydantic.BaseModel
Filler standing in for a message the compression deletion pass emptied.
Carries no payload. A message reduced to nothing but tombstones keeps this single block instead of an empty content list, so it stays in the Bedrock payload at its original role and turn alternation survives without relocating content. The Bedrock boundary renders it as <Deleted in compression>. Produced only by the compression deletion pass and stored only at the DELETED tier; the verbatim original thread (what the SDK and UI render) never contains one.
Parameters
data AnyAttributes
AgentCompressionFillerContent.content_type
AgentContent
Type alias for all possible content types within agent messages.
AgentContentType
Bases: roboto.compat.StrEnum
Enumeration of different types of content within agent messages.
Defines the various content types that can be included in agent messages.
Attributes
AgentContentType.CLIENT_CONTEXT
What the caller was looking at when they composed the message this block sits on.
Superseded shape: the same payload used to be persisted as a whole ROBOTO-role message whose text was a <ctx>...</ctx> marker (ENG-2185). Readers still accept that form for threads written before this type existed; nothing emits it any more.
AgentContentType.COMPRESSION_FILLER
Stand-in block kept in a message the deletion pass emptied entirely.
A message reduced to nothing but tombstones would break user/assistant alternation if it dropped from the payload. Replacing its content with this single filler keeps the message — and its role — in place. The model sees it as <Deleted in compression>. Only the cross-message deletion pass produces it, so it appears only inside a DELETED-tier compressed variant, never in the verbatim original thread the SDK and UI read.
AgentContentType.DELETED
Tombstone marking a content block elided by compression.
Appears only inside a DELETED-tier compressed variant. Both producers — message-tier compression dropping a pure-filler text run, and the cross-message deletion pass dropping a whole tool exchange — store their output at the DELETED tier, so a message carrying one is always a DELETED-tier variant. Never in the verbatim original thread the SDK and UI read.
AgentDeletedContent
Bases: pydantic.BaseModel
Tombstone for a content block removed by compression.
Carries no payload — its presence records that a block once occupied this slot, and it converts to None at the Bedrock boundary so the block drops from the LLM payload. Produced when compression drops a block — a pure-filler text run at message compression, or a whole redundant tool exchange in the cross-message deletion pass — and stored only at the DELETED tier, so a message carrying one is always a DELETED-tier variant. A message reduced to nothing but tombstones does not drop: it is replaced with a single AgentCompressionFillerContent so it keeps its role and turn. The verbatim original thread (what the SDK and UI render) never contains one.
Parameters
data AnyAttributes
AgentDeletedContent.content_type
AgentErrorContent
Bases: pydantic.BaseModel
Error content within an agent message.
Used when message generation fails due to an error or is cancelled by the user.
Parameters
data AnyAttributes
AgentErrorContent.content_type
AgentErrorContent.error_code
Optional error code for programmatic handling.
AgentErrorContent.error_message
User-friendly error message describing what went wrong.
AgentErrorEvent
Bases: pydantic.BaseModel
Signals that message generation failed or was cancelled.
Parameters
data AnyAgentEvent
AgentGoalStatus
Bases: roboto.compat.StrEnum
Lifecycle of a per-turn declared goal.
Goals begin PENDING when registered. They transition to ACHIEVED when the corresponding achieve-tool reports success, or to FAILED when the runner’s corrective re-prompt budget for the turn is exhausted (or when the worker cannot construct an achieve-tool for the goal).
Attributes
AgentMessage
Bases: pydantic.BaseModel
A single message within an agent thread.
Represents one message in the conversation, containing the sender role, content blocks, and generation status. Messages can contain multiple content blocks of different types (text, tool use, tool results).
Parameters
data AnyAttributes
AgentMessage.content
List of content blocks that make up this message.
AgentMessage.is_complete()
Check if message generation is complete.
Returns
True if the message status is COMPLETED, False otherwise.
AgentMessage.is_unsuccessful()
Check if message generation failed or was cancelled.
Returns
True if the message status is FAILED or CANCELLED, False otherwise.
Attributes
AgentMessage.text()
Create a simple text message.
Convenience method for creating a message containing only text content.
Parameters
text strThe text content for the message.
role AgentRoleThe role of the message sender. Defaults to USER.
Returns
AgentMessage instance containing the text content.
AgentMessageStatus
Bases: roboto.compat.StrEnum
Enumeration of possible message generation states.
Tracks the lifecycle of message generation from initiation to completion.
Attributes
AgentMessageStatus.COMPLETED
Message generation has finished and content is complete.
AgentMessageStatus.GENERATING
Message content is currently being generated.
AgentMessageStatus.NOT_STARTED
Message has been queued but generation has not begun.
AgentMessageStatus.is_terminal()
Check if the message generation is in a terminal state.
Returns
True if the message is in a terminal state, False otherwise.
AgentRole
Bases: roboto.compat.StrEnum
Enumeration of possible roles in an agent thread.
Defines the different participants that can send messages in a thread.
AgentStartTextEvent
Bases: pydantic.BaseModel
Signals the beginning of text generation in a chat response.
Parameters
data AnyAgentSubtask
Bases: pydantic.BaseModel
A lightweight checklist item under a top-level task.
Parameters
data AnyAttributes
AgentSubtaskStatus
Bases: roboto.compat.StrEnum
Lifecycle state of a sub-task.
Sub-tasks are never activated independently — they are implicitly active with their parent task — so they have no in_progress state.
AgentTask
Bases: pydantic.BaseModel
A top-level task the agent is tracking within a thread.
Parameters
data AnyAttributes
AgentTask.conclusion
Outcome recorded when the task was completed. None until then.
AgentTask.description
Longer description delimiting the task’s scope and intent.
AgentTask.start
Where the task most recently became in_progress. None if never started.
AgentTask.subtasks
Ordered sub-tasks. A task cannot be completed until all of these are done.
AgentTask.task_id
Thread-monotonic id, stable for the life of the thread. The model references this id to start or complete the task.
AgentTaskBoundary
Bases: pydantic.BaseModel
Position in the conversation where a top-level task’s active span begins or ends.
Identifies the assistant message and the content block within it whose tool call drove the transition, so callers can anchor a task to the part of the thread that worked on it.
Parameters
data AnyAgentTaskMinimal
Bases: pydantic.BaseModel
Minimal acknowledgement returned by the task mutation tools.
The full list reaches the model through the per-turn injected context, so the mutation tools echo only the affected task’s id and resulting status.
Parameters
data AnyAttributes
AgentTaskStatus
Bases: roboto.compat.StrEnum
Lifecycle state of a top-level agent task.
Attributes
AgentTaskStatus.IN_PROGRESS
The single active task. At most one task per thread is in this state.
AgentTextContent
Bases: pydantic.BaseModel
Text content within an agent message.
Parameters
data AnyAttributes
AgentTextDeltaEvent
Bases: pydantic.BaseModel
Contains incremental text content as the AI generates its response.
Parameters
data AnyAttributes
AgentTextEndEvent
Bases: pydantic.BaseModel
Signals the completion of text generation in a chat response.
Parameters
data AnyAgentThread
An interactive AI agent session within the Roboto platform.
An AgentThread is a conversational interface with Roboto’s AI assistant, enabling users to ask questions, request data analysis, and interact with their robotics data through natural language. Sessions maintain conversation history and support streaming responses for real-time interaction.
The primary control-flow primitives are run() (drive the session forward with auto-dispatch of client-side tools) and events() (observe events as the agent generates without taking any actions).
Usage
Fire-and-forget with client-side tools:
from roboto.ai import AgentThread, client_tool
@client_tool
def remember(fact: str) -> str:
"""Store a fact in long-term memory."""
...
session = AgentThread.start("Remember my favorite color is blue.", client_tools=[remember])
session.run()Observing events as they happen:
session = AgentThread.start("Explain machine learning.")
for event in session.events():
if isinstance(event, AgentTextDeltaEvent):
print(event.text, end="", flush=True)Parameters
roboto_client Optional[roboto.client_tools Optional[collections.Properties
AgentThread.client_tool_names
Names of client-side tools registered on this session with callbacks.
AgentThread.events()
Yield events from the agent as they are generated.
Polls the session and yields AgentEvent objects as new content arrives. Does not auto-dispatch client-side tools — if the session reaches AgentThreadStatus.CLIENT_TOOL_TURN, the generator returns and the caller is expected to call submit_client_tool_results() (and then call events() again to continue). For automatic dispatch, use run().
Parameters
tick floatPolling interval in seconds between checks for new content.
timeout Optional[float]Maximum time to wait in seconds. If None, waits indefinitely.
Yields
AgentEvent objects (AgentStartTextEvent, AgentTextDeltaEvent, AgentTextEndEvent, AgentToolUseEvent, AgentToolResultEvent, AgentErrorEvent) as they become available. Text events are scoped to a single message: an AgentTextEndEvent is emitted at the end of each message that carried text, so adjacent assistant messages produce separate start/end pairs.
Raises
TimeoutErrorIf timeout elapses before the session pauses.
Return type
Usage
Stream text output as it arrives:
for event in session.events():
if isinstance(event, AgentTextDeltaEvent):
print(event.text, end="", flush=True)AgentThread.fork()
Fork this session’s history up to a specific message into a new session owned by the caller.
Fork access mirrors read access: anyone who can read the source session can fork it. A ThreadVisibility.ORG-visible session can be forked by any member of its org; a ThreadVisibility.PRIVATE session can be forked only by its creator or a Roboto admin. The new session carries the source session’s org_id so tool calls resolve against the source org’s data, and is always created with ThreadVisibility.PRIVATE visibility, owned by the caller, regardless of the source’s visibility — so forks never appear in another member’s session list.
Parameters
message_sequence_num intHighest message sequence number (inclusive) to copy.
Returns
A new AgentThread instance for the forked session.
Raises
If the caller is not a member of the source session’s org, or the source session is ThreadVisibility.PRIVATE and the caller is neither its creator nor a Roboto admin.
If message_sequence_num is out of range or points at a message still generating.
AgentThread.from_id()
Retrieve an existing agent thread by its unique identifier.
Loads a previously created thread from the Roboto platform, allowing users to resume conversations and access message history.
Parameters
thread_id strUnique identifier for the thread. Accepts current ath_* identifiers as well as legacy ags_* and ch_* identifiers.
roboto_client Optional[roboto.HTTP client for API communication. If None, uses the default client.
load_messages boolWhether to load the thread’s messages. If False, the thread’s messages will be empty.
Returns
AgentThread instance representing the existing thread.
Raises
If the thread does not exist.
If the caller lacks permission to access the thread.
Usage
Resume an existing thread:
thread = AgentThread.from_id("ath_abc123")
print(f"Thread has {len(thread.messages)} messages")
# Thread has 5 messagesProperties
AgentThread.goals
Goals declared across this thread’s turns, oldest first.
Each entry is an AgentThreadGoalView SDK wrapper that delegates the goal-record fields and adds three resolved properties:
AgentThreadGoalView.achieve_tool_use— the LLM’s achieve-tool invocation, located byachieve_tool_use_id.AgentThreadGoalView.achieve_tool_result— the matching tool result block, if one was persisted.AgentThreadGoalView.result— the typed, per-goal-typeGoalResult(with the LLM’s submitted payload parsed into typed fields).
Returns an empty list when the thread declared no goals or when the underlying record was fetched without loading them — call refresh() if you expect goals to be present but the list is empty.
Wrappers are cached against the underlying goals-list identity: repeated reads return the same list (and the same per-goal wrappers) until a refresh installs a fresh goals list, at which point the cache is invalidated transparently. Callers may rely on identity comparison across reads against the same snapshot.
AgentThread.invoke_skill()
Manually invoke a skill into this thread.
Thin wrapper around send() that builds a single-element invoke_skills list and sends it with no user message — kept for SDK ergonomics on the common “invoke exactly one skill” case.
Parameters
skill_id strThe skill to invoke.
version Optional[int]Optional version number. Must exist on the skill (any version is invokable). If omitted, the latest (MAX(version)) version is used.
Returns
Self for method chaining.
Usage
Apply a skill’s latest version to the current turn:
thread.invoke_skill("sk_qa_review")Apply a specific version of the skill:
thread.invoke_skill("sk_qa_review", version=2)Properties
AgentThread.latest_message
The most recent message in the conversation, or None if no messages exist.
AgentThread.messages
Complete list of messages in the conversation in chronological order.
AgentThread.refresh()
Update the session with the latest messages and status.
Fetches any new messages or status changes from the server and updates the local session state.
Returns
Self for method chaining.
AgentThread.register_client_tool()
Register a client-side tool for auto-dispatch in subsequent turns.
The tool’s spec is not sent to the backend by this call; pass it via the client_tools= argument on send(), send_text(), or submit_client_tool_results() on the next outbound request.
Parameters
The ClientTool to register.
Returns
Self for method chaining.
AgentThread.run()
Drive the session forward until it is the user’s turn.
Polls the session, auto-dispatching any pending client-side tool invocations against the callbacks registered with this session (via start(), send(), or register_client_tool()). Returns once the session status is AgentThreadStatus.USER_TURN.
If the agent requests a client-side tool that has no registered callback, an error result is submitted automatically with a descriptive message so the agent can recover, and execution continues. If a registered callback raises, the exception is caught and also submitted as an error result.
Parameters
on_event Optional[OnEvent]Optional callback invoked for each AgentEvent as the agent generates (text deltas, tool uses, tool results, start/end markers). Use this for progress display or logging.
tick floatPolling interval in seconds between status checks.
timeout Optional[float]Total time budget in seconds across the whole loop. If None, waits indefinitely.
Returns
Self for method chaining.
Raises
TimeoutErrorIf the timeout budget is exhausted before the session reaches USER_TURN.
RuntimeErrorIf the session is in CLIENT_TOOL_TURN with no messages (i.e. a server state that should not be reachable), or if an unexpected AgentThreadStatus value is observed.
RobotoHttpExceptionPropagated from the underlying submit_client_tool_results() POST if the server rejects the submission (for example, a concurrent caller already answered the tool-use).
Usage
Fire-and-forget:
session = AgentThread.start("Remember my favorite color is blue.", client_tools=[remember])
session.run()With progress logging:
def log(event):
if isinstance(event, AgentToolUseEvent):
print(f"[tool-use] {event.name}({event.input})")
session.run(on_event=log)AgentThread.send()
Send a structured message to the session.
Parameters
message Optional[roboto.AgentMessage object containing the message content and metadata. Optional when at least one entry is provided in goals or invoke_skills; in that case the server synthesizes a minimal user message for the turn.
client_context Optional[roboto.Optional ClientViewingContext describing what the calling client is currently viewing when this message was composed. Informational only; see AgentThread.start() for full semantics.
client_tools Optional[collections.Optional client-side tools to add or update for this and subsequent turns. ClientTool callbacks are registered on the session for auto-dispatch.
analysis_scope Optional[roboto.Optional replacement AnalysisScope. When provided, overwrites the session’s current scope for all subsequent tool invocations. When None, the session’s existing scope (if any) is left untouched.
goals Optional[collections.Optional structured goals to declare for this turn. The agent runner enforces achievement of every declared goal before completing the turn.
invoke_skills Optional[collections.Optional sequence of InvokeSkillSpec to invoke one or more stored skills as part of this turn. For each entry the server fabricates a load_skill tool_use/tool_result pair after message (if any). When message and goals are both omitted, the fabricated pairs alone trigger the turn. Latest (MAX(version)) is used when version is omitted on an entry.
Returns
Self for method chaining.
Raises
If the message format is invalid.
If the caller lacks permission to send messages.
If the thread was started on another surface (see AgentThreadRecord.origin). Fork it to keep going.
AgentThread.send_text()
Send a text message to the session.
Convenience method for sending a simple text message without needing to construct an AgentMessage.
Parameters
text strText content to send to the assistant.
client_context Optional[roboto.Optional ClientViewingContext describing what the calling client is currently viewing.
client_tools Optional[collections.Optional client-side tools to add or update.
analysis_scope Optional[roboto.Optional replacement AnalysisScope; see send() for update semantics.
goals Optional[collections.Optional goals to declare for this turn. See send() for full semantics.
Returns
Self for method chaining.
Raises
If the text is empty or invalid.
If the caller lacks permission to send messages.
If the thread was started on another surface (see AgentThreadRecord.origin). Fork it to keep going.
AgentThread.set_pinned()
Pin or unpin this thread for the calling user.
A pin is a personal bookmark: it promotes the thread to the top of the caller’s chat sidebar and is invisible to everyone else. Anyone who may read the thread may pin it, including teammates on a thread whose visibility is ORG.
Setting the state the thread already has is accepted and changes nothing; re-pinning in particular does not move the thread back to the top of the pinned block.
Leaves pinned_at untouched on this instance’s record: only the thread listing and search endpoints populate that field.
Parameters
pinned boolTrue to pin, False to unpin.
Returns
Self for method chaining.
Raises
If the thread does not exist.
If the caller is not a member of the thread’s org, or the thread is private and the caller did not create it.
Usage
Pin a thread to the top of your sidebar:
thread.set_pinned(True)Unpin it again:
thread.set_pinned(False)AgentThread.set_visibility()
Re-scope who may read this thread.
Only the thread’s creator may call this. Roboto admins can read every thread but cannot re-scope one they did not create. Setting the visibility a thread already has is accepted and leaves it unchanged.
Parameters
ThreadVisibility.ORG to open the thread to every member of the thread’s organization, or ThreadVisibility.PRIVATE to restrict it back to its creator.
Returns
Self for method chaining.
Raises
If the thread does not exist.
If the caller is not a member of the thread’s org, or is a member but did not create the thread.
AgentThread.start()
Start a new agent session with an initial message.
Creates a new session and sends the initial message to begin the conversation. The AI assistant will process the message and generate a response, which can be driven to completion with run() or observed event-by-event with events().
Parameters
message Optional[Union[str, roboto.Initial message to start the conversation. Can be a text string, a single AgentMessage, or a sequence of AgentMessage objects for multi-turn initialization. Optional when at least one entry is provided in goals or invoke_skills; in those cases the server synthesizes a minimal user message — implicitly “achieve the goals” or “apply the invoked skills” — and the agent will work the turn from there.
client_context Optional[roboto.Optional ClientViewingContext describing what the calling client (e.g. the Web UI) is currently displaying when this session is started. Lets the agent resolve deictic references like “this dataset” without the user spelling them out. Informational only; does not gate authorization or scope tools — see analysis_scope for that.
system_prompt Optional[str]Optional system prompt to customize the AI assistant’s behavior for this conversation.
model_profile Optional[str]Optional model profile ID (e.g. “standard”, “advanced”). Defaults to the deployment’s default profile.
org_id Optional[str]Organization ID to create the session in. If None, uses the caller’s default organization.
client_tools Optional[collections.Optional list of client-side tools to make available to the agent. Accepts ClientTool instances (which include a callback for auto-dispatch) and bare ClientToolSpec objects (which describe the tool but require the caller to submit results manually).
analysis_scope Optional[roboto.Optional AnalysisScope for the session (e.g. a time window or topic-pattern filter). When provided, the scope is persisted on the session and delivered to every tool invocation on the server side. Individual tools opt in to honoring the scope as they are adopted.
goals Optional[collections.Optional structured goals to declare for the first turn. When provided, message may be omitted; the server will synthesize a minimal user message and the agent runner will enforce achievement of every declared goal before completing the turn.
invoke_skills Optional[collections.Optional sequence of InvokeSkillSpec to invoke one or more stored skills at session start, in order. For each entry the server fabricates a load_skill tool_use/tool_result pair after any seeded message; with no message and no goals, the fabricated pairs alone seed the conversation. Each skill must be visible to the caller (org skill or own private skill); the version must exist on the skill but is not required to be the latest one. Latest (MAX(version)) is used when version is omitted on an entry.
available_skills Optional[collections.Optional explicit set of skills the AI may auto-invoke during this session, replacing the registry it would otherwise derive from the caller’s skill subscriptions. None (the default) keeps the subscription-derived behavior; an empty list gives the AI no auto-invokable skills; a non-empty list of AvailableSkillSpec makes exactly those skill versions auto-invokable and ignores subscriptions and per-user ai_version pins. Each entry may reference any org skill or the caller’s own private skill (visibility only — no subscription needed), at any version. This is session configuration, not a turn trigger: it does not by itself satisfy the “needs a message, goal, or invoked skill” requirement. Distinct from invoke_skills, which seeds skill bodies into the opening transcript.
roboto_client Optional[roboto.HTTP client for API communication. If None, uses the default client.
Returns
AgentThread instance representing the newly created session.
Raises
If the message format is invalid.
If the caller lacks permission to create sessions.
Usage
Start and drive a session with client-side tools:
from roboto.ai import client_tool
@client_tool
def recall(query: str) -> str:
"""Search long-term memory for facts matching a query."""
...
session = AgentThread.start("What do you remember?", client_tools=[recall])
session.run()Properties
AgentThread.status
Current status of the thread.
AgentThread.submit_client_tool_results()
Submit results of client-side tool execution to resume the session.
On success the server has persisted every submitted tool_result and queued a new worker turn; the local record.status flips to ROBOTO_TURN to match. See the inline comment for why the next delta poll cannot communicate that transition on its own.
Parameters
results collections.Tool results from client-side execution.
client_tools Optional[collections.Optional updated client-side tools for the next invocation. ClientTool callbacks are registered on the session for auto-dispatch.
Returns
Self for method chaining.
AgentThread.submit_feedback()
Submit structured feedback on a specific assistant message in this session.
Persists categorized feedback so it can be reviewed by Roboto operators. Re-submitting from the same user on the same message overwrites sentiment, categories, and notes on the existing row rather than creating a duplicate; the feedback_id and original created/created_by are preserved.
Parameters
message_sequence_num intZero-indexed position of the assistant message being rated.
Overall rating direction.
categories Optional[list[roboto.Zero or more categories describing the feedback. Must match sentiment. FeedbackCategory.OTHER is always permitted but requires notes.
notes Optional[str]Free-text notes. Required when FeedbackCategory.OTHER is among the categories.
Returns
The persisted feedback as a UserFeedbackRecord. Admin triage columns (admin_label, admin_note, resolved, resolved_by, resolved_at) are intentionally not part of this shape — they are only visible through the admin API.
Raises
If the message is still generating, the sentiment/category combination is invalid, or OTHER is used without notes.
If the caller cannot access this session.
If message_sequence_num is out of range.
Properties
AgentThread.tasks
The thread’s task list, ordered by position.
Returns an empty list when the thread has no tasks or when the underlying record was fetched without loading them — call refresh() if you expect tasks but the list is empty.
AgentThread.transcript
Human-readable transcript of the entire conversation.
Returns a formatted string containing all messages in the conversation, with role indicators and message content clearly separated.
AgentThread.unregister_client_tool()
Remove a previously registered client-tool callback.
This only removes the local callback. The backend was told about the tool in StartAgentThreadRequest client_tools (or via a later send()) and may still emit tool_use events for it; once the callback is gone, run() will submit an error result for those invocations so the agent can recover. There is no server-side deregistration API.
The tool name remains recorded as a declared client tool on this session, so the dispatcher still treats it as client-side (and not as a server tool whose result the server will post).
Parameters
name strName of the client tool to unregister.
Returns
True if a callback was removed, False if no callback was registered under name.
Properties
AgentThread.visibility
Read scope for this thread: creator-only (PRIVATE) or open to the thread’s org (ORG).
AgentThreadDelta
Bases: pydantic.BaseModel
Incremental update to an agent thread.
Contains only the changes since the last synchronization, used for efficient real-time updates without transferring the entire thread history.
Parameters
data AnyAttributes
AgentThreadDelta.continuation_token
Updated token for the next incremental synchronization.
AgentThreadDelta.goals
Latest snapshot of every goal declared in the thread, ordered by allocation. None means there has been no change since the previous delta — clients should retain the snapshot they already hold. An empty list means the thread has no declared goals. A non-empty list is the authoritative current snapshot and replaces any prior value.
AgentThreadDelta.messages_by_idx
New or updated messages indexed by their position in the conversation.
AgentThreadDelta.reset_from_message_sequence_num
Discard held messages from this index onward before applying this delta.
A delta’s messages normally extend what a client already holds, because the server sends only content the client has not seen. That breaks when a turn is abandoned partway and regenerated: the replacement message reuses the same index, so what the client holds at that index is text from an attempt that no longer exists, and appending to it would splice the real reply onto a discarded draft.
When this field is set, the client must truncate its held messages to indices strictly below it, then apply messages_by_idx and adopt continuation_token as usual — the server has rewound the stream to that point and will resend it. None (the common case) means append as normal.
AgentThreadDelta.tasks
Latest snapshot of the thread’s task list, ordered by position. None means no change since the previous delta — clients should retain the snapshot they already hold. An empty list means the thread has no tasks. A non-empty list is the authoritative current snapshot and replaces any prior value.
AgentThreadGoalRecord
Bases: pydantic.BaseModel
Customer-visible read shape of a goal declared on an agent thread.
Parameters
data AnyAttributes
AgentThreadGoalRecord.achieve_tool_use_id
tool_use_id of the achieve-tool invocation associated with this goal. Populated by the turn runner on every achieve-tool attempt, so its final value depends on the goal’s terminal status:
ACHIEVED: thetool_use_idof the successful invocation.FAILED: thetool_use_idof the last attempted invocation, orNoneif the LLM never invoked the achieve-tool before the retry budget exhausted.PENDING:None(or the most recent attempt so far).
Use with AgentThread.goals and the GoalResult accessor on the SDK wrapper to locate the exact AgentToolUseContent / AgentToolResultContent pair without scanning by tool name.
AgentThreadGoalRecord.concluded_at
Timestamp when the goal transitioned to a terminal state (ACHIEVED or FAILED). None while the goal is still PENDING.
AgentThreadGoalRecord.goal_data
The validated goal payload as JSON. Use to_agent_goal() to recover the typed model the caller declared.
AgentThreadGoalRecord.goal_type
Discriminator selecting which AgentGoal model the goal_data payload conforms to (e.g. "dataset_summary").
AgentThreadGoalRecord.message_sequence_num
Index in the thread’s full messages list of the AgentRole.USER message that declared this goal. Use to render goals adjacent to the turn they were attached to.
AgentThreadGoalRecord.status
Current lifecycle state of the goal.
AgentThreadGoalRecord.to_agent_goal()
Re-hydrate goal_data into the typed AgentGoal the caller declared.
Returns
The validated, discriminated AgentGoal instance — for "dataset_summary" rows, a DatasetSummaryAgentGoal; for "dataset_triage" rows, a DatasetTriageGoal; etc.
AgentThreadGoalView
SDK-side wrapper around an AgentThreadGoalRecord.
Holds a back-reference to a messages list (the parent thread’s full message history) so the achieve-tool invocation can be located via achieve_tool_use_id without forcing the caller to do the lookup by hand.
The wrapper is value-like: instantiating it does not copy the underlying record. Callers should not mutate it; mutations on the parent thread (via run / refresh) are visible through the wrapper’s resolved properties because the messages list is shared.
Parameters
Properties
AgentThreadGoalView.achieve_tool_result
The matching tool-result block for achieve_tool_use, if the runner persisted one before the turn terminated.
For a FAILED goal whose last attempt errored mid-flight (or whose tool_result chunk never landed), this returns None even when achieve_tool_use is non-null.
AgentThreadGoalView.achieve_tool_use
The achieve-tool invocation the LLM submitted for this goal.
Returns None when achieve_tool_use_id is None (no attempt has been recorded) or when no matching block is present in the thread’s messages — the latter can happen if the caller is holding a thread snapshot that pre-dates the achieve-tool being persisted. In that case, a refresh of the thread should bring the block into view.
AgentThreadGoalView.achieve_tool_use_id
tool_use_id of the achieve-tool invocation associated with this goal — see AgentThreadGoalRecord.achieve_tool_use_id for the per-status semantics.
AgentThreadGoalView.concluded_at
Timestamp when the goal reached a terminal state, or None while still PENDING.
AgentThreadGoalView.created
Timestamp when the goal was registered.
AgentThreadGoalView.goal_data
The original goal-declaration payload. Use to_agent_goal() to re-hydrate into the typed AgentGoal model.
AgentThreadGoalView.goal_type
Discriminator selecting which AgentGoal model the goal was declared as. Equivalent to self.record.goal_type.
AgentThreadGoalView.message_sequence_num
Index of the user-role message that declared this goal.
AgentThreadGoalView.record
The underlying wire record. Useful for callers that want the unwrapped pydantic shape (e.g. for JSON serialization).
AgentThreadGoalView.result
Typed, per-goal-type result for the achieve-tool invocation.
Returns None when no terminal achieve-tool invocation is available (PENDING goal, or FAILED with no attempted invocation), when the matching tool_use cannot be located in the thread’s messages, or when the persisted input is malformed enough to fail validation against the achieve-input model. In all three cases callers can still inspect achieve_tool_use / achieve_tool_result directly for debugging.
The returned object is one of the concrete subclasses of GoalResult (e.g. DatasetSummaryGoalResult), so callers can isinstance-dispatch or simply read the typed fields. The status field reflects the goal’s terminal status, so the same accessor works for both ACHIEVED and FAILED outcomes.
AgentThreadGoalView.status
Current lifecycle state of the goal.
AgentThreadGoalView.to_agent_goal()
Re-hydrate the goal declaration into its typed AgentGoal model. Delegates to AgentThreadGoalRecord.to_agent_goal().
Return type
AgentThreadRecord
Bases: pydantic.BaseModel
Complete record of an agent thread.
Contains all the persistent data for a thread including metadata, message history, and synchronization state.
Parameters
data AnyAttributes
AgentThreadRecord.continuation_token
Token used for incremental updates and synchronization.
AgentThreadRecord.created_by_principal
Serialized RobotoPrincipal ("ptype:id") that started this thread, e.g. "user:jo@example.com" or "invocation:iv_123". Unlike created_by, this preserves whether the thread was driven by a person, a device, or an action invocation. None on threads created before this field existed.
AgentThreadRecord.created_from_agent_id
If this thread was started via the agent launch flow, the id of the agent that produced it. None for threads started directly through POST /v1/ai/threads. Forks do not inherit this field — a fork is its own thread.
AgentThreadRecord.created_from_trigger_id
If a trigger’s start_agent target launched this thread, the id of that trigger. None for every other thread, including one launched from the same agent by a person. Set alongside created_from_agent_id, which names the agent; this names what decided to run it. Forks do not inherit this field — a fork is its own thread.
AgentThreadRecord.forked_from_message_sequence_num
Message sequence number in the source thread that this fork was taken from.
Populated in tandem with forked_from_thread_id; both are None for threads that were not created as a fork.
AgentThreadRecord.forked_from_thread_id
If this thread was forked, the id of the source thread. None otherwise.
Deserialization also accepts the legacy forked_from_session_id spelling for backward compatibility.
AgentThreadRecord.goals
Goals declared across this thread’s turns, ordered by the turn that declared them. None means goals were not loaded for this record; an empty list means they were loaded but the thread never declared any.
AgentThreadRecord.messages
Complete list of messages in the conversation.
AgentThreadRecord.model_config
model_config #Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
AgentThreadRecord.model_profile
Model profile used for this agent thread (e.g., ‘standard’, ‘advanced’).
AgentThreadRecord.origin
The surface that owns this thread.
Set by Roboto when the thread is created; it cannot be supplied by a caller. A thread owned by a surface outside Roboto refuses new messages over the API, raising RobotoThreadReadOnlyException; reading, cancelling, and rating it stay open, and a fork does not inherit the origin, so the copy is writable.
None on threads created before this field existed, and equivalent to ThreadOrigin.API — every surface that predates the field was Roboto’s own. It stays nullable until those rows are backfilled.
AgentThreadRecord.pinned_at
When the calling user pinned this thread, or None if they have not.
A pin is a personal bookmark, so two users reading the same thread see different values here. Pin and unpin through roboto.ai.agent_thread.AgentThread.set_pinned(). Only GET /v1/ai/threads and POST /v1/ai/threads/search report it; reads of a single thread leave it None whatever the pin state.
AgentThreadRecord.tasks
The thread’s task list, ordered by AgentTask.position. None means tasks were not loaded for this record; an empty list means they were loaded but the thread has none.
AgentThreadRecord.thread_id
Unique identifier for this agent thread.
Deserialization also accepts the legacy session_id and chat_id spellings for backward compatibility; the canonical attribute name is thread_id.
AgentThreadRecord.visibility
Who can read this thread. PRIVATE (the default) restricts reads to the created_by user and Roboto admins; ORG opens the thread to every member of org_id.
AgentThreadStatus
Bases: roboto.compat.StrEnum
Enumeration of possible agent thread states.
Tracks the overall status of an agent thread from creation to termination.
Attributes
AgentThreadStatus.CLIENT_TOOL_TURN
Client must execute pending tool uses and submit results.
AgentThreadStatus.GOALS_FAILED
The agent runner exhausted its corrective re-prompt budget without achieving every declared goal for the most-recent turn. Signals to clients that the thread needs human intervention before it can continue.
AgentThreadStatus.NOT_STARTED
Thread has been created but no messages have been sent.
AgentThreadSubject
Bases: pydantic.BaseModel
Canonical record of an entity an AgentThread applies to.
Used to answer “which agent threads are about this dataset / file?” — the dataset detail page’s Agent Threads tab is one consumer; future surfaces that want to discover threads by entity will use the same record.
Parameters
data AnyAttributes
AgentThreadSubject.association_id
Identifier of the entity the thread applies to — e.g. a dataset id or file id.
AgentThreadSubject.model_config
model_config #Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
AgentThreadSubject.note
Short, free-form explanation of how the subject came to be attached (e.g. why this thread applies to that entity).
AgentToolDetailResponse
Bases: pydantic.BaseModel
Unsanitized tool request and response details for an agent tool invocation.
Parameters
data AnyAttributes
AgentToolDetailResponse.tool_result
AgentToolDetailResponse.tool_use
AgentToolResultContent
Bases: pydantic.BaseModel
Tool execution result content within an agent message.
Parameters
data AnyAttributes
AgentToolResultContent.content_type
AgentToolResultContent.payload
What the tool returned: free-form text, or a JSON object or array of structured data.
Independent of any model provider’s wire format (provider-agnostic, like AgentToolUseContent.input). None on results written before this field existed; use resolve_payload() to read old and new results uniformly.
AgentToolResultContent.raw_response
Legacy provider-formatted response envelope (Bedrock toolResult shape).
Kept so results written before payload existed remain readable; deprecated for new readers, who should call resolve_payload() instead of parsing this field.
Populated only where the server-side envelope is in scope: threads read over the API arrive with this field stripped (and, for legacy rows, with payload synthesized from it server-side before the strip), so API/SDK readers should not expect it.
AgentToolResultContent.resolve_payload()
Return what the tool returned, whichever field carries it.
Prefers payload. Results written before that field existed carry only the legacy envelope, from which the equivalent value is reconstructed via synthesize_tool_result_payload().
Returns
The tool’s text or JSON output, or None when neither field carries a recognizable value.
Attributes
AgentToolResultContent.runtime_ms
Wall-clock execution time of the tool in milliseconds.
AgentToolResultContent.tool_use_id
Identifier of the tool invocation this result corresponds to.
AgentToolResultEvent
Bases: pydantic.BaseModel
Contains the result of a tool invocation.
Parameters
data AnyAttributes
AgentToolResultEvent.output
Raw tool output payload (from the underlying tool_result’s raw_response). May be None for errored invocations or for tools that return no data.
AgentToolResultEvent.runtime_ms
Wall-clock execution time of the tool in milliseconds, as reported by the tool-result content. None only if the underlying content omits it.
AgentToolUseContent
Bases: pydantic.BaseModel
Tool usage request content within an agent message.
Parameters
data AnyAttributes
AgentToolUseContent.content_type
AgentToolUseContent.input
Parsed tool input parameters chosen by the LLM (provider-agnostic).
AgentToolUseContent.raw_request
Raw, unparsed request payload for this tool invocation.
AgentToolUseContent.tool_use_id
Unique identifier for this tool invocation, used to correlate with its result.
AgentToolUseEvent
Bases: pydantic.BaseModel
Signals that the AI is invoking a tool to gather information.
Parameters
data AnyAnalysisScope
Bases: pydantic.BaseModel
The slice of data an agent is expected to analyze.
An AnalysisScope is delivered to every AgentTool invocation on the server side. Individual tools opt in to honoring the scope as they are adopted; this SDK type carries the configuration, it does not itself enforce anything. Fields set to None are unconstrained on that dimension; an AnalysisScope with every field None is equivalent to no scope at all.
Parameters
data AnyAttributes
AnalysisScope.end_time
Upper bound (inclusive) of the analysis window, expressed as nanoseconds since the Unix epoch.
AnalysisScope.merge()
Zipper-merge override onto this scope, dimension by dimension.
For each field, the override value wins when it is set (not None); otherwise this scope’s value carries through. Used to reconcile an invoke-time scope (override) against an authored template scope (self): a launch can override individual dimensions while inheriting the rest.
Parameters
override AnalysisScopeReturn type
Attributes
AnalysisScope.start_time
Lower bound (inclusive) of the analysis window, expressed as nanoseconds since the Unix epoch.
AvailableSkillSpec
Bases: pydantic.BaseModel
One entry in a thread’s explicit AI-invokable skill set.
Embedded in StartAgentThreadRequest.available_skills. Unlike InvokeSkillSpec — which seeds a skill into the opening transcript as a turn trigger — this struct only declares that a skill version is available for the AI to auto-invoke via its load_skill tool during the thread. The route layer resolves access (org visibility, private gating) and version selection; this struct only carries the caller’s choice.
Defined locally to avoid the roboto.ai <-> roboto.domain.skills import cycle.
Parameters
data AnyAttributes
AvailableSkillSpec.skill_id
Target skill’s ID. Must be visible to the caller — an org-shared skill, or the caller’s own private skill. A subscription is not required; the per-thread set bypasses subscription state entirely.
AvailableSkillSpec.version
Optional. If omitted, resolves to the skill’s latest (MAX(version)) row.
Pins the exact version exposed to the AI for this thread. Subscriptions and their per-user ai_version pins are ignored when a thread carries an explicit available_skills set.
ClientTool
A client-side tool with an execution callback.
Wraps a Python callable as a tool that the Roboto agent can request the client to execute. The tool’s JSON schema is inferred from the callable’s type hints; the tool description and per-parameter descriptions are taken from the function’s Google-style docstring unless passed explicitly.
Most callers build ClientTools via the client_tool() decorator or ClientTool.from_function() rather than instantiating this class directly.
Usage
Using the decorator — descriptions come from the docstring:
@client_tool
def remember(fact: str, tags: Optional[list[str]] = None) -> str:
"""Store a fact in long-term memory.
Args:
fact: A standalone sentence worth remembering.
tags: Optional tags for later retrieval.
"""
...Using Annotated[T, Field(...)] instead (takes precedence over the docstring):
from typing import Annotated
from pydantic import Field
@client_tool
def recall(
query: Annotated[str, Field(description="Substring to search for.")],
) -> str:
"""Search long-term memory."""
...Using the factory with explicit overrides:
tool = ClientTool.from_function(
my_fn,
name="store_fact",
description="Store a fact in long-term memory.",
)Parameters
fn collections.name strdescription strinput_schema dict[str, Any]ClientTool.from_function()
Build a ClientTool from a Python callable.
The tool’s name defaults to fn.__name__. The tool description defaults to the summary-and-body of fn’s docstring (everything before the first Google-style section header like Args: or Returns:). Per-parameter descriptions are pulled from the docstring’s Args: section, and can be overridden with typing.Annotated[T, pydantic.Field(description="...")] or param: T = pydantic.Field(description="...").
Parameters
fn collections.The callable to invoke when the tool is dispatched.
name Optional[str]Override for the tool name (default: fn.__name__).
description Optional[str]Override for the tool description (default: the docstring’s summary-and-body). Required if fn has no docstring.
input_schema Optional[dict[str, Any]]Override for the input JSON Schema (default: inferred from fn’s type hints and docstring).
Returns
A ClientTool wrapping the given callable.
Raises
ValueErrorIf the description cannot be resolved, or if input_schema is not provided and the signature cannot be automatically converted (e.g. uses *args or **kwargs).
Properties
ClientTool.spec
Declarative spec sent to the Roboto backend.
ClientToolResult
Bases: pydantic.BaseModel
Result of executing a client-side tool.
Parameters
data AnyAttributes
ClientToolResult.tool_use_id
Identifier of the tool invocation this result corresponds to.
ClientToolResultStatus
ClientToolSpec
Bases: pydantic.BaseModel
Declarative specification for a client-side tool.
Unlike AgentTool (which is an ABC with a __call__ method for server-side execution), ClientToolSpec is a plain data model. The backend includes it in the LLM’s tool list but never executes it — the client is responsible for execution and submitting the result.
Parameters
data AnyFeedbackCategory
Bases: roboto.compat.StrEnum
Taxonomy of feedback categories.
Which categories are valid depends on sentiment (see category_is_valid_for_sentiment()). OTHER is always permitted; when OTHER is among the selected categories, notes is required.
Attributes
FeedbackCategory.CORRECT
FeedbackCategory.FORMATTING
FeedbackCategory.GOOD_TOOL_USE
FeedbackCategory.HELPFUL
FeedbackCategory.INCOMPLETE
FeedbackCategory.INCORRECT
FeedbackCategory.OTHER
FeedbackCategory.REFUSED_VALID_REQUEST
FeedbackCategory.SLOW
FeedbackCategory.TOOL_FAILURE
FeedbackCategory.UNSAFE
FeedbackSentiment
ForkAgentThreadRequest
Bases: pydantic.BaseModel
Request payload for forking an agent thread at a specific message.
Parameters
data AnyAttributes
ForkAgentThreadRequest.message_sequence_num
Highest message sequence number (inclusive) to copy into the new thread.
InvokeSkillSpec
Bases: pydantic.BaseModel
Spec for invoking a skill as part of a turn trigger.
Embedded in SendMessageRequest and StartAgentThreadRequest. The route layer resolves access (org visibility, private gating) and version selection; this struct only carries the caller’s choice.
Defined locally to avoid the roboto.ai ↔ roboto.domain.skills import cycle.
Parameters
data AnyAttributes
InvokeSkillSpec.skill_id
Target skill’s ID. Must be visible to the caller (own private skill or an org-shared skill); the route layer rejects unauthorized invocations before the spec reaches the service.
InvokeSkillSpec.version
Optional. If omitted, resolves to the skill’s latest (MAX(version)) row.
Note this is the structural latest, not the caller’s pinned ai_version: a manually-invoked chip runs MAX(version) regardless of what the caller’s AI auto-invoke is pinned to. Use Skill.set_ai_version() to control the pin separately.
NEGATIVE_CATEGORIES
POSITIVE_CATEGORIES
PinThreadRequest
Bases: pydantic.BaseModel
Request body for POST /v1/ai/threads/<thread_id>/pin, which pins or unpins a thread for the caller.
Parameters
data AnyAttributes
PinThreadRequest.pinned
Pin state the thread should have for the calling user after the call.
RobotoAgentGoalsFailedException
Bases: RuntimeError
Raised by AgentThread.run() when a goal-bearing turn exhausts its corrective re-prompt budget without satisfying every declared goal.
Inherits RuntimeError rather than RobotoException because this is a strictly client-side condition — the session is paused, not errored on the wire — and the project’s Roboto*Exception hierarchy is reserved for exceptions cast from HTTP status codes by the SDK’s response layer. The typed shape still lets callers distinguish “the agent gave up on declared goals” from “I have a bug in my client state machine,” which is what motivated lifting it out of the opaque RuntimeError run() used to raise on unexpected statuses.
The session is in AgentThreadStatus.GOALS_FAILED; inspect AgentThread.messages and AgentThreadRecord.goals for detail about which goals failed and why.
Parameters
thread_id strAttributes
RobotoAgentGoalsFailedException.thread_id
thread_id #SendMessageRequest
Bases: pydantic.BaseModel
Request payload for sending a message to an agent thread.
Contains the message content and optional context for the AI assistant.
Parameters
data AnyAttributes
SendMessageRequest.analysis_scope
Optional replacement analysis scope. When provided, overwrites the thread’s current analysis scope; the new scope takes effect for this turn’s tool invocations and every turn thereafter. When None, the thread’s existing analysis scope is left untouched (there is currently no wire-format way to clear a scope via send).
SendMessageRequest.client_context
Optional ClientViewingContext describing what the client was viewing when this message was composed. Wire field is client_context; the legacy context alias is accepted during the migration window and will be dropped in a future release.
SendMessageRequest.client_tools
Optional client-side tools available for this invocation.
SendMessageRequest.goals
Goals declared for this turn. The agent runner enforces achievement: it gates a per-turn achieve-tool against each goal and re-prompts until every goal is satisfied or a per-turn retry budget is exhausted. May be omitted; when present, message becomes optional. Capped at MAX_GOALS_PER_TURN entries (see the constant for rationale).
SendMessageRequest.invoke_skills
Skills to invoke as part of this turn, in order. The server fabricates one LoadSkillTool tool_use + tool_result pair per entry and appends them to the transcript after message (if any). When message is empty and no goals are declared, the fabricated pairs become the turn trigger themselves — useful for chip-only invocations that don’t carry a typed prompt. Pass a single-element list for the common “invoke one skill” case.
SendMessageRequest.message
Message content to send. May be omitted when at least one goal is declared in goals; in that case the server synthesizes a minimal user message so the LLM has a turn-initiating prompt.
StartAgentThreadRequest
Bases: pydantic.BaseModel
Request payload for starting a new agent thread.
Contains the initial messages and configuration for creating a new conversation.
Parameters
data AnyAttributes
StartAgentThreadRequest.analysis_scope
Optional analysis scope for the thread. Delivered to every tool invocation on the server side; individual tools opt in to honoring it. None means no scope.
StartAgentThreadRequest.available_skills
Explicit set of skills the AI may auto-invoke during this thread, replacing the subscription-derived load_skill registry.
Tri-state:
None(the default) — the AI’sload_skillregistry is derived per turn from the caller’s skill subscriptions, as usual.[]— the AI has no auto-invokable skills for this thread.- a non-empty list — exactly these skill versions are auto-invokable; the caller’s subscriptions and per-user
ai_versionpins are ignored.
Each entry may reference any org-shared skill or the caller’s own private skill (visibility only — no subscription required), at any version. One version per skill: duplicate skill_id entries are rejected. Resolved once at thread start and frozen onto the thread; later subscription changes and skill-body edits do not propagate into it. Capped at MAX_AVAILABLE_SKILLS entries.
Distinct from invoke_skills: available_skills configures what the AI can reach for, while invoke_skills seeds skill bodies into the opening transcript as a turn trigger. It is configuration, not a trigger — a request carrying only available_skills and no messages / goals / invoke_skills is still rejected.
StartAgentThreadRequest.client_context
Optional ClientViewingContext describing what the client was viewing when this thread was started. Wire field is client_context; the legacy context alias is accepted during the migration window and will be dropped in a future release.
StartAgentThreadRequest.client_tools
Optional client-side tools available for this invocation.
StartAgentThreadRequest.goals
Goals declared for the first turn. The agent runner enforces achievement: it gates a per-turn achieve-tool against each goal and re-prompts until every goal is satisfied or a per-turn retry budget is exhausted. May be omitted; when present, messages may be empty. Capped at MAX_GOALS_PER_TURN entries (see the constant for rationale).
StartAgentThreadRequest.invoke_skills
Skills to invoke at thread start, in order. The server fabricates one LoadSkillTool tool_use + tool_result pair per entry and appends them to the transcript after any seeded messages. When messages is empty and no goals are declared, the fabricated pairs become the thread seed. Pass a single-element list for the common “invoke one skill” case.
StartAgentThreadRequest.messages
Initial messages to start the conversation with. May be empty when at least one goal is declared in goals; in that case the server synthesizes a minimal user message so the LLM has a turn-initiating prompt.
StartAgentThreadRequest.model_config
model_config #Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
StartAgentThreadRequest.model_profile
Optional model profile ID for the thread (e.g. ‘standard’, ‘advanced’).
StartAgentThreadRequest.system_prompt
Optional system prompt to customize AI assistant behavior.
StartAgentThreadRequest.visibility
Who may read the resulting thread after it is created. PRIVATE (the default) restricts reads to the creator and Roboto admins; ORG lets any member of the thread’s org read it and makes the thread visible to org members on POST /v1/ai/threads/search. The default is PRIVATE so that a thread started via POST /v1/ai/threads does not leak to the rest of the org until the caller opts in; threads created through the agent launch flow default to ORG instead, since agents exist to share workflows across teammates.
SubmitFeedbackRequest
Bases: pydantic.BaseModel
Request body for submitting feedback on an assistant message.
One row per (session, message, user); resubmitting replaces the previous sentiment/categories/notes rather than adding a new row.
Parameters
data AnyAttributes
SubmitFeedbackRequest.categories
Categories describing what was good or bad. Semantically a set: duplicates are dropped and the persisted order is enum-value sort, not request order.
SubmitFeedbackRequest.notes
Free-text notes. Whitespace-only input is normalised to None before persistence. Required when FeedbackCategory.OTHER is selected.
SubmitToolResultsRequest
Bases: pydantic.BaseModel
Request payload for submitting client-side tool execution results.
Parameters
data AnyAttributes
SubmitToolResultsRequest.client_tools
Optional updated client-side tools for the next invocation.
SubmitToolResultsRequest.tool_results
Tool results from client-side execution.
ThreadOrigin
Bases: roboto.compat.StrEnum
The surface an AgentThreadRecord was started from, and the one that owns it.
Distinct from AgentThreadRecord.created_by_principal, which records who started a thread. This records where the conversation lives, which is what decides whether it can be added to over the API.
Import as roboto.ai.agent_thread.ThreadOrigin.
Attributes
ThreadOrigin.API
Started through Roboto itself – the web app, the CLI, the SDK, or a direct REST call.
These surfaces read the thread back from Roboto rather than mirroring it somewhere else, so there is nothing for a new turn to fall out of sync with and the thread stays writable.
ThreadOrigin.SLACK
Started by mentioning @Roboto in Slack, and mirrored into that Slack conversation.
ThreadVisibility
Bases: roboto.compat.StrEnum
Read-scope for an AgentThreadRecord.
Set when the thread is created, and changed afterwards only by the thread’s creator, via roboto.ai.agent_thread.AgentThread.set_visibility() (POST /v1/ai/threads/<thread_id>/visibility). Roboto admins read every thread but cannot re-scope one they did not create.
Import as roboto.ai.agent_thread.ThreadVisibility.
Attributes
ThreadVisibility.ORG
Any member of the thread’s organization (and Roboto admins) may read the thread.
Default for threads produced by the agent launch flow, since agents exist to share workflows across teammates. Forks of an ORG thread do not inherit visibility — every fork lands as PRIVATE.
ThreadVisibility.PRIVATE
Only the creating user (and Roboto admins) may read the thread.
Default for threads created via POST /v1/ai/threads so an in-flight experiment does not leak to the rest of the org until the caller opts in.
UpdateThreadVisibilityRequest
Bases: pydantic.BaseModel
Request payload for re-scoping who may read an agent thread.
Sent to POST /v1/ai/threads/<thread_id>/visibility by roboto.ai.agent_thread.AgentThread.set_visibility().
Parameters
data AnyAttributes
UpdateThreadVisibilityRequest.visibility
Read-scope the thread has once the call returns.
UserFeedbackRecord
Bases: pydantic.BaseModel
Customer-facing projection of AgentFeedbackRecord.
Excludes every admin-only column (admin_label, admin_note, resolved, resolved_by, resolved_at) so routes that serve an end user never return internal triage state. Use this as the return type of any non-admin endpoint that surfaces feedback, including the response to the submitter’s own submit call.
The admin endpoints continue to return AgentFeedbackRecord directly.
Parameters
data AnyAttributes
UserFeedbackRecord.categories
Categories describing the feedback. May be empty.
UserFeedbackRecord.from_admin_record()
Project an AgentFeedbackRecord down to the user-facing shape.
Use at the boundary of any non-admin route that materialises a full admin record from persistence — the projection guarantees no admin triage column accidentally escapes to a customer response.
The projection is driven by cls.model_fields rather than a hand list of columns: a new submitter-controlled column added to both records flows through automatically, and a new admin-only column on AgentFeedbackRecord is silently dropped here (which is what we want for privacy). The matching test asserts the admin-only field set has not drifted unexpectedly.
Parameters
record AgentFeedbackRecordReturn type
Attributes
UserFeedbackRecord.message_sequence_num
Zero-indexed position of the assistant message within the session.
UserFeedbackRecord.modified
When the submitter last updated this feedback.
category_is_valid_for_sentiment()
Report whether category is a permitted choice under sentiment.
FeedbackCategory.OTHER is always permitted.
Parameters
category FeedbackCategorysentiment FeedbackSentimentReturn type
client_tool()
Decorator that converts a function into a ClientTool.
Usable bare (@client_tool) or with keyword overrides (@client_tool(description="...")). See ClientTool.from_function() for how descriptions are resolved.
Usage
Bare — infers everything from the function, including per-parameter descriptions from the docstring’s Args: section:
@client_tool
def remember(fact: str) -> str:
"""Store a fact in long-term memory.
Args:
fact: A standalone sentence worth remembering.
"""
...With overrides:
@client_tool(name="store_fact", description="Persist a fact.")
def _store(fact: str) -> str: ...