roboto.ai.agent_thread#
Submodules#
Package Contents#
- class roboto.ai.agent_thread.AdminUpdateFeedbackRequest(/, **data)#
Bases:
pydantic.BaseModelTriage fields editable by Roboto admins.
Fields omitted from the request (
NotSet) are left unchanged. Fields explicitly set toNoneclear the column back toNULL. Fields set to a value overwrite the column.Setting
resolvedtoTrueadditionally stampsresolved_atandresolved_byserver-side; setting it back toFalseclears them.- Parameters:
data (Any)
- admin_label: str | None | roboto.sentinels.NotSetType#
- admin_note: str | None | roboto.sentinels.NotSetType#
- model_config#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- resolved: bool | roboto.sentinels.NotSetType#
- type roboto.ai.agent_thread.AgentContent = AgentTextContent | AgentToolUseContent | AgentToolResultContent | AgentErrorContent#
Type alias for all possible content types within agent messages.
- class roboto.ai.agent_thread.AgentContentType#
Bases:
roboto.compat.StrEnumEnumeration of different types of content within agent messages.
Defines the various content types that can be included in agent messages.
- ERROR = 'error'#
Error information when message generation fails.
- TEXT = 'text'#
Plain text content from users or AI responses.
- TOOL_RESULT = 'tool_result'#
Results returned from tool executions.
- TOOL_USE = 'tool_use'#
Tool invocation requests from the AI assistant.
- class roboto.ai.agent_thread.AgentErrorContent(/, **data)#
Bases:
pydantic.BaseModelError content within an agent message.
Used when message generation fails due to an error or is cancelled by the user.
- Parameters:
data (Any)
- content_type: Literal[AgentContentType]#
- error_code: str | None = None#
Optional error code for programmatic handling.
- error_message: str#
User-friendly error message describing what went wrong.
- class roboto.ai.agent_thread.AgentErrorEvent(/, **data)#
Bases:
pydantic.BaseModelSignals that message generation failed or was cancelled.
- Parameters:
data (Any)
- error_code: str | None = None#
Optional error code for programmatic handling.
- error_message: str#
User-friendly error message describing what went wrong.
- type roboto.ai.agent_thread.AgentEvent = Union[AgentStartTextEvent, AgentTextDeltaEvent, AgentTextEndEvent, AgentToolUseEvent, AgentToolResultEvent, AgentErrorEvent]#
- class roboto.ai.agent_thread.AgentGoalStatus#
Bases:
roboto.compat.StrEnumLifecycle 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).
- ACHIEVED = 'achieved'#
Goal’s corresponding achieve-tool was invoked successfully.
- FAILED = 'failed'#
Goal could not be achieved within the turn’s retry budget.
- PENDING = 'pending'#
Goal has been registered but not yet completed.
- class roboto.ai.agent_thread.AgentMessage(/, **data)#
Bases:
pydantic.BaseModelA 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 (Any)
- content: list[AgentContent]#
List of content blocks that make up this message.
- created: datetime.datetime = None#
Timestamp when this message was created.
- is_complete()#
Check if message generation is complete.
- Returns:
True if the message status is COMPLETED, False otherwise.
- Return type:
bool
- is_unsuccessful()#
Check if message generation failed or was cancelled.
- Returns:
True if the message status is FAILED or CANCELLED, False otherwise.
- Return type:
bool
- status: AgentMessageStatus#
Current generation status of this message.
- classmethod text(text, role=AgentRole.USER)#
Create a simple text message.
Convenience method for creating a message containing only text content.
- Parameters:
text (str) – The text content for the message.
role (AgentRole) – The role of the message sender. Defaults to USER.
- Returns:
AgentMessage instance containing the text content.
- Return type:
- class roboto.ai.agent_thread.AgentMessageStatus#
Bases:
roboto.compat.StrEnumEnumeration of possible message generation states.
Tracks the lifecycle of message generation from initiation to completion.
- CANCELLED = 'cancelled'#
Message generation was cancelled by the user.
- COMPLETED = 'completed'#
Message generation has finished and content is complete.
- FAILED = 'failed'#
Message generation failed due to an error.
- GENERATING = 'generating'#
Message content is currently being generated.
- NOT_STARTED = 'not_started'#
Message has been queued but generation has not begun.
- is_terminal()#
Check if the message generation is in a terminal state.
- Returns:
True if the message is in a terminal state, False otherwise.
- Return type:
bool
- class roboto.ai.agent_thread.AgentRole#
Bases:
roboto.compat.StrEnumEnumeration of possible roles in an agent thread.
Defines the different participants that can send messages in a thread.
- ASSISTANT = 'assistant'#
AI agent responding to user queries and requests.
- ROBOTO = 'roboto'#
Roboto system providing tool results and system information.
- USER = 'user'#
Human user sending messages to the agent.
- class roboto.ai.agent_thread.AgentStartTextEvent(/, **data)#
Bases:
pydantic.BaseModelSignals the beginning of text generation in a chat response.
- Parameters:
data (Any)
- class roboto.ai.agent_thread.AgentTextContent(/, **data)#
Bases:
pydantic.BaseModelText content within an agent message.
- Parameters:
data (Any)
- text: str#
The actual text content of the message.
- class roboto.ai.agent_thread.AgentTextDeltaEvent(/, **data)#
Bases:
pydantic.BaseModelContains incremental text content as the AI generates its response.
- Parameters:
data (Any)
- text: str#
Text fragment from the streaming response.
- class roboto.ai.agent_thread.AgentTextEndEvent(/, **data)#
Bases:
pydantic.BaseModelSignals the completion of text generation in a chat response.
- Parameters:
data (Any)
- class roboto.ai.agent_thread.AgentThread(record, roboto_client=None, client_tools=None)#
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) andevents()(observe events as the agent generates without taking any actions).Examples
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.http.RobotoClient])
client_tools (Optional[collections.abc.Sequence[Union[roboto.ai.agent_thread.client_tool.ClientTool, roboto.ai.agent_thread.record.ClientToolSpec]]])
- property client_tool_names: list[str]#
Names of client-side tools registered on this session with callbacks.
- Return type:
list[str]
- events(tick=0.2, timeout=None)#
Yield events from the agent as they are generated.
Polls the session and yields
AgentEventobjects as new content arrives. Does not auto-dispatch client-side tools — if the session reachesAgentThreadStatus.CLIENT_TOOL_TURN, the generator returns and the caller is expected to callsubmit_client_tool_results()(and then callevents()again to continue). For automatic dispatch, userun().- Parameters:
tick (float) – Polling interval in seconds between checks for new content.
timeout (Optional[float]) – Maximum time to wait in seconds. If None, waits indefinitely.
- Yields:
AgentEventobjects (AgentStartTextEvent,AgentTextDeltaEvent,AgentTextEndEvent,AgentToolUseEvent,AgentToolResultEvent,AgentErrorEvent) as they become available. Text events are scoped to a single message: anAgentTextEndEventis emitted at the end of each message that carried text, so adjacent assistant messages produce separate start/end pairs.- Raises:
TimeoutError – If
timeoutelapses before the session pauses.- Return type:
collections.abc.Generator[roboto.ai.agent_thread.event.AgentEvent, None, None]
Examples
Stream text output as it arrives:
>>> for event in session.events(): ... if isinstance(event, AgentTextDeltaEvent): ... print(event.text, end="", flush=True)
- fork(message_sequence_num)#
Fork this session’s history up to a specific message into a new session owned by the caller.
Available to the session’s creator (forking their own session) and to Roboto admins (
is_roboto_admin) forking anyone’s session. The new session carries the source session’sorg_idso tool calls resolve against the source org’s data. The new session is owned by the caller, so admin forks of a customer session never appear in the customer’s session list.- Parameters:
message_sequence_num (int) – Highest message sequence number (inclusive) to copy.
- Returns:
A new
AgentThreadinstance for the forked session.- Raises:
RobotoUnauthorizedException – If the caller is not a member of the source session’s org, or is a member but is neither the source session’s creator nor a Roboto admin.
RobotoInvalidRequestException – If
message_sequence_numis out of range or points at a message still generating.
- Return type:
- classmethod from_id(thread_id, roboto_client=None, load_messages=True)#
Retrieve an existing agent session by its unique identifier.
Loads a previously created session from the Roboto platform, allowing users to resume conversations and access message history.
- Parameters:
thread_id (str) – Unique identifier for the session. Accepts both
ags_*and legacych_*identifiers.roboto_client (Optional[roboto.http.RobotoClient]) – HTTP client for API communication. If None, uses the default client.
load_messages (bool) – Whether to load the session’s messages. If False, the session’s messages will be empty.
- Returns:
AgentThread instance representing the existing session.
- Raises:
RobotoNotFoundException – If the session does not exist.
RobotoUnauthorizedException – If the caller lacks permission to access the session.
- Return type:
Examples
Resume an existing session:
>>> session = AgentThread.from_id("ags_abc123") >>> print(f"Session has {len(session.messages)} messages") Session has 5 messages
- invoke_skill(skill_id, version=None)#
Manually invoke a skill into this thread.
Thin wrapper around
send()that builds a single-elementinvoke_skillslist and sends it with no user message — kept for SDK ergonomics on the common “invoke exactly one skill” case.- Parameters:
skill_id (str) – The 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.
- Return type:
Examples
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)
- property latest_message: roboto.ai.agent_thread.record.AgentMessage | None#
The most recent message in the conversation, or None if no messages exist.
- Return type:
- property messages: list[roboto.ai.agent_thread.record.AgentMessage]#
Complete list of messages in the conversation in chronological order.
- Return type:
- 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.
- Return type:
- register_client_tool(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 onsend(),send_text(), orsubmit_client_tool_results()on the next outbound request.- Parameters:
tool (roboto.ai.agent_thread.client_tool.ClientTool) – The ClientTool to register.
- Returns:
Self for method chaining.
- Return type:
- run(*, on_event=None, tick=0.2, timeout=None)#
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(), orregister_client_tool()). Returns once the session status isAgentThreadStatus.USER_TURN.If the agent requests a client-side tool that has no registered callback, an
errorresult 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 anerrorresult.- Parameters:
on_event (Optional[OnEvent]) – Optional callback invoked for each
AgentEventas the agent generates (text deltas, tool uses, tool results, start/end markers). Use this for progress display or logging.tick (float) – Polling 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:
TimeoutError – If the
timeoutbudget is exhausted before the session reachesUSER_TURN.RuntimeError – If the session is in
CLIENT_TOOL_TURNwith no messages (i.e. a server state that should not be reachable), or if an unexpectedAgentThreadStatusvalue is observed.RobotoHttpException – Propagated from the underlying
submit_client_tool_results()POST if the server rejects the submission (for example, a concurrent caller already answered the tool-use).
- Return type:
Examples
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)
- send(message=None, *, client_context=None, client_tools=None, analysis_scope=None, goals=None, invoke_skills=None)#
Send a structured message to the session.
- Parameters:
message (Optional[roboto.ai.agent_thread.record.AgentMessage]) – AgentMessage object containing the message content and metadata. Optional when at least one entry is provided in
goalsorinvoke_skills; in that case the server synthesizes a minimal user message for the turn.client_context (Optional[roboto.ai.core.ClientViewingContext]) – Optional
ClientViewingContextdescribing what the calling client is currently viewing when this message was composed. Informational only; seeAgentThread.start()for full semantics.client_tools (Optional[collections.abc.Sequence[Union[roboto.ai.agent_thread.client_tool.ClientTool, roboto.ai.agent_thread.record.ClientToolSpec]]]) – 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.ai.core.AnalysisScope]) – Optional replacement
AnalysisScope. When provided, overwrites the session’s current scope for all subsequent tool invocations. WhenNone, the session’s existing scope (if any) is left untouched.goals (Optional[collections.abc.Sequence[roboto.ai.goals.AgentGoal]]) – 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.abc.Sequence[roboto.ai.agent_thread.record.InvokeSkillSpec]]) – Optional sequence of
InvokeSkillSpecto invoke one or more stored skills as part of this turn. For each entry the server fabricates aload_skilltool_use/tool_result pair aftermessage(if any). Whenmessageandgoalsare both omitted, the fabricated pairs alone trigger the turn. Latest (MAX(version)) is used whenversionis omitted on an entry.
- Returns:
Self for method chaining.
- Raises:
RobotoInvalidRequestException – If the message format is invalid.
RobotoUnauthorizedException – If the caller lacks permission to send messages.
- Return type:
- send_text(text, *, client_context=None, client_tools=None, analysis_scope=None, goals=None)#
Send a text message to the session.
Convenience method for sending a simple text message without needing to construct an
AgentMessage.- Parameters:
text (str) – Text content to send to the assistant.
client_context (Optional[roboto.ai.core.ClientViewingContext]) – Optional
ClientViewingContextdescribing what the calling client is currently viewing.client_tools (Optional[collections.abc.Sequence[Union[roboto.ai.agent_thread.client_tool.ClientTool, roboto.ai.agent_thread.record.ClientToolSpec]]]) – Optional client-side tools to add or update.
analysis_scope (Optional[roboto.ai.core.AnalysisScope]) – Optional replacement
AnalysisScope; seesend()for update semantics.goals (Optional[collections.abc.Sequence[roboto.ai.goals.AgentGoal]]) – Optional goals to declare for this turn. See
send()for full semantics.
- Returns:
Self for method chaining.
- Raises:
RobotoInvalidRequestException – If the text is empty or invalid.
RobotoUnauthorizedException – If the caller lacks permission to send messages.
- Return type:
- classmethod start(message=None, *, client_context=None, system_prompt=None, model_profile=None, org_id=None, client_tools=None, analysis_scope=None, goals=None, invoke_skills=None, available_skills=None, roboto_client=None)#
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 withevents().- Parameters:
message (Optional[Union[str, roboto.ai.agent_thread.record.AgentMessage, collections.abc.Sequence[roboto.ai.agent_thread.record.AgentMessage]]]) – 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
goalsorinvoke_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.ai.core.ClientViewingContext]) – Optional
ClientViewingContextdescribing 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 — seeanalysis_scopefor 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.abc.Sequence[Union[roboto.ai.agent_thread.client_tool.ClientTool, roboto.ai.agent_thread.record.ClientToolSpec]]]) – Optional list of client-side tools to make available to the agent. Accepts
ClientToolinstances (which include a callback for auto-dispatch) and bareClientToolSpecobjects (which describe the tool but require the caller to submit results manually).analysis_scope (Optional[roboto.ai.core.AnalysisScope]) – Optional
AnalysisScopefor 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.abc.Sequence[roboto.ai.goals.AgentGoal]]) – Optional structured goals to declare for the first turn. When provided,
messagemay 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.abc.Sequence[roboto.ai.agent_thread.record.InvokeSkillSpec]]) – Optional sequence of
InvokeSkillSpecto invoke one or more stored skills at session start, in order. For each entry the server fabricates aload_skilltool_use/tool_result pair after any seededmessage; with nomessageand nogoals, 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 whenversionis omitted on an entry.available_skills (Optional[collections.abc.Sequence[roboto.ai.agent_thread.record.AvailableSkillSpec]]) – 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 ofAvailableSkillSpecmakes exactly those skill versions auto-invokable and ignores subscriptions and per-userai_versionpins. 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 frominvoke_skills, which seeds skill bodies into the opening transcript.roboto_client (Optional[roboto.http.RobotoClient]) – HTTP client for API communication. If None, uses the default client.
- Returns:
AgentThread instance representing the newly created session.
- Raises:
RobotoInvalidRequestException – If the message format is invalid.
RobotoUnauthorizedException – If the caller lacks permission to create sessions.
- Return type:
Examples
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()
- property status: roboto.ai.agent_thread.record.AgentThreadStatus#
Current status of the thread.
- Return type:
- submit_client_tool_results(results, client_tools=None)#
Submit results of client-side tool execution to resume the session.
On success the server has persisted every submitted
tool_resultand queued a new worker turn; the localrecord.statusflips toROBOTO_TURNto match. See the inline comment for why the next delta poll cannot communicate that transition on its own.- Parameters:
results (collections.abc.Sequence[roboto.ai.agent_thread.record.ClientToolResult]) – Tool results from client-side execution.
client_tools (Optional[collections.abc.Sequence[Union[roboto.ai.agent_thread.client_tool.ClientTool, roboto.ai.agent_thread.record.ClientToolSpec]]]) – Optional updated client-side tools for the next invocation. ClientTool callbacks are registered on the session for auto-dispatch.
- Returns:
Self for method chaining.
- Return type:
- submit_feedback(message_sequence_num, sentiment, categories=None, notes=None)#
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, andnoteson the existing row rather than creating a duplicate; thefeedback_idand originalcreated/created_byare preserved.- Parameters:
message_sequence_num (int) – Zero-indexed position of the assistant message being rated.
sentiment (roboto.ai.agent_thread.feedback.FeedbackSentiment) – Overall rating direction.
categories (Optional[list[roboto.ai.agent_thread.feedback.FeedbackCategory]]) – Zero or more categories describing the feedback. Must match
sentiment.FeedbackCategory.OTHERis always permitted but requiresnotes.notes (Optional[str]) – Free-text notes. Required when
FeedbackCategory.OTHERis 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:
RobotoInvalidRequestException – If the message is still generating, the sentiment/category combination is invalid, or
OTHERis used without notes.RobotoUnauthorizedException – If the caller cannot access this session.
RobotoNotFoundException – If
message_sequence_numis out of range.
- Return type:
- property thread_id: str#
Unique identifier for this thread.
- Return type:
str
- property transcript: str#
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.
- Return type:
str
- unregister_client_tool(name)#
Remove a previously registered client-tool callback.
This only removes the local callback. The backend was told about the tool in
StartAgentThreadRequestclient_tools(or via a latersend()) and may still emittool_useevents 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 (str) – Name of the client tool to unregister.
- Returns:
Trueif a callback was removed,Falseif no callback was registered undername.- Return type:
bool
- class roboto.ai.agent_thread.AgentThreadDelta(/, **data)#
Bases:
pydantic.BaseModelIncremental 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 (Any)
- continuation_token: str#
Updated token for the next incremental synchronization.
- goals: list[AgentThreadGoalRecord] | None = None#
Latest snapshot of every goal declared in the thread, ordered by allocation.
Nonemeans 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.
- messages_by_idx: dict[int, AgentMessage]#
New or updated messages indexed by their position in the conversation.
- status: AgentThreadStatus | None = None#
Updated status of the agent thread.
- title: str | None = None#
Updated title of the agent thread.
- class roboto.ai.agent_thread.AgentThreadGoalRecord(/, **data)#
Bases:
pydantic.BaseModelCustomer-visible read shape of a goal declared on an agent thread.
- Parameters:
data (Any)
- concluded_at: datetime.datetime | None = None#
Timestamp when the goal transitioned to a terminal state (ACHIEVED or FAILED).
Nonewhile the goal is still PENDING.
- created: datetime.datetime#
Timestamp when the goal was registered.
- goal_data: dict[str, Any]#
The validated goal payload as JSON. Use
to_agent_goal()to recover the typed model the caller declared.
- goal_type: str#
Discriminator selecting which
AgentGoalmodel thegoal_datapayload conforms to (e.g."dataset_summary").
- message_sequence_num: int#
Index in the thread’s full messages list of the
AgentRole.USERmessage that declared this goal. Use to render goals adjacent to the turn they were attached to.
- status: AgentGoalStatus#
Current lifecycle state of the goal.
- class roboto.ai.agent_thread.AgentThreadRecord(/, **data)#
Bases:
pydantic.BaseModelComplete record of an agent thread.
Contains all the persistent data for a thread including metadata, message history, and synchronization state.
- Parameters:
data (Any)
- continuation_token: str#
Token used for incremental updates and synchronization.
- created: datetime.datetime#
Timestamp when this agent thread was created.
- created_by: str#
User ID of the person who created this agent thread.
- created_from_agent_id: str | None = None#
If this thread was started via the agent launch flow, the id of the agent that produced it.
Nonefor threads started directly throughPOST /v1/ai/threads. Forks do not inherit this field — a fork is its own thread.
- forked_from_message_sequence_num: int | None = None#
Message sequence number in the source thread that this fork was taken from.
Populated in tandem with
forked_from_thread_id; both areNonefor threads that were not created as a fork.
- forked_from_thread_id: str | None = None#
If this thread was forked, the id of the source thread.
Noneotherwise.Deserialization also accepts the legacy
forked_from_session_idspelling for backward compatibility.
- goals: list[AgentThreadGoalRecord] | None = None#
Goals declared across this thread’s turns, ordered by the turn that declared them.
Nonemeans goals were not loaded for this record; an empty list means they were loaded but the thread never declared any.
- messages: list[AgentMessage] = None#
Complete list of messages in the conversation.
- model_profile: str | None = None#
Model profile used for this agent thread (e.g., ‘standard’, ‘advanced’).
- org_id: str#
Organization ID that owns this agent thread.
- status: AgentThreadStatus#
Current status of this agent thread.
- thread_id: str = None#
Unique identifier for this agent thread.
Deserialization also accepts the legacy
session_idandchat_idspellings for backward compatibility; the canonical attribute name isthread_id.
- title: str | None = None#
Title of this agent thread.
- visibility: ThreadVisibility#
Who can read this thread.
PRIVATE(the default) restricts reads to thecreated_byuser and Roboto admins;ORGopens the thread to every member oforg_id.
- class roboto.ai.agent_thread.AgentThreadStatus#
Bases:
roboto.compat.StrEnumEnumeration of possible agent thread states.
Tracks the overall status of an agent thread from creation to termination.
- CLIENT_TOOL_TURN = 'client_tool_turn'#
Client must execute pending tool uses and submit results.
- GOALS_FAILED = '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.
- NOT_STARTED = 'not_started'#
Thread has been created but no messages have been sent.
- ROBOTO_TURN = 'roboto_turn'#
Roboto is generating a message.
- USER_TURN = 'user_turn'#
User has the turn to send a message.
- class roboto.ai.agent_thread.AgentThreadSubject(/, **data)#
Bases:
pydantic.BaseModelCanonical record of an entity an
AgentThreadapplies 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 (Any)
- association_id: str#
Identifier of the entity the thread applies to — e.g. a dataset id or file id.
- model_config#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- note: str#
Short, free-form explanation of how the subject came to be attached (e.g. why this thread applies to that entity).
- class roboto.ai.agent_thread.AgentToolDetailResponse(/, **data)#
Bases:
pydantic.BaseModelUnsanitized tool request and response details for an agent tool invocation.
- Parameters:
data (Any)
- tool_result: roboto.ai.core.record.AgentToolResultContent#
- class roboto.ai.agent_thread.AgentToolResultContent(/, **data)#
Bases:
pydantic.BaseModelTool execution result content within an agent message.
- Parameters:
data (Any)
- content_type: Literal[AgentContentType]#
- raw_response: dict[str, Any] | None = None#
Raw, unparsed response payload from tool execution.
- runtime_ms: int#
Wall-clock execution time of the tool in milliseconds.
- status: str#
Outcome of the tool execution (e.g. ‘success’, ‘error’).
- tool_name: str#
Name of the tool that was executed.
- tool_use_id: str#
Identifier of the tool invocation this result corresponds to.
- class roboto.ai.agent_thread.AgentToolResultEvent(/, **data)#
Bases:
pydantic.BaseModelContains the result of a tool invocation.
- Parameters:
data (Any)
- name: str#
Name of the tool that was invoked.
- output: dict[str, Any] | None = None#
Raw tool output payload (from the underlying tool_result’s
raw_response). May beNonefor errored invocations or for tools that return no data.
- runtime_ms: int | None = None#
Wall-clock execution time of the tool in milliseconds, as reported by the tool-result content.
Noneonly if the underlying content omits it.
- success: bool#
Whether the tool invocation succeeded.
- tool_use_id: str#
Unique identifier for this tool invocation.
- class roboto.ai.agent_thread.AgentToolUseContent(/, **data)#
Bases:
pydantic.BaseModelTool usage request content within an agent message.
- Parameters:
data (Any)
- content_type: Literal[AgentContentType]#
- input: dict[str, Any] | None = None#
Parsed tool input parameters chosen by the LLM (provider-agnostic).
- raw_request: dict[str, Any] | None = None#
Raw, unparsed request payload for this tool invocation.
- tool_name: str#
Name of the tool the LLM is requesting to invoke.
- tool_use_id: str#
Unique identifier for this tool invocation, used to correlate with its result.
- class roboto.ai.agent_thread.AgentToolUseEvent(/, **data)#
Bases:
pydantic.BaseModelSignals that the AI is invoking a tool to gather information.
- Parameters:
data (Any)
- input: dict[str, Any] | None = None#
Parsed tool input parameters chosen by the LLM.
- name: str#
Name of the tool being invoked.
- tool_use_id: str#
Unique identifier for this tool invocation.
- class roboto.ai.agent_thread.AnalysisScope(/, **data)#
Bases:
pydantic.BaseModelThe slice of data an agent is expected to analyze.
An
AnalysisScopeis delivered to everyAgentToolinvocation 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 toNoneare unconstrained on that dimension; anAnalysisScopewith every fieldNoneis equivalent to no scope at all.- Parameters:
data (Any)
- end_time: int | None = None#
Upper bound (inclusive) of the analysis window, expressed as nanoseconds since the Unix epoch.
- start_time: int | None = None#
Lower bound (inclusive) of the analysis window, expressed as nanoseconds since the Unix epoch.
- class roboto.ai.agent_thread.AvailableSkillSpec(/, **data)#
Bases:
pydantic.BaseModelOne entry in a thread’s explicit AI-invokable skill set.
Embedded in
StartAgentThreadRequest.available_skills. UnlikeInvokeSkillSpec— 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 itsload_skilltool 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.skillsimport cycle.- Parameters:
data (Any)
- skill_id: str#
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.
- version: int | None = None#
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_versionpins are ignored when a thread carries an explicitavailable_skillsset.
- class roboto.ai.agent_thread.ClientTool(fn, *, name, description, input_schema)#
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 orClientTool.from_function()rather than instantiating this class directly.Examples
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.abc.Callable[Ellipsis, Any])
name (str)
description (str)
input_schema (dict[str, Any])
- classmethod from_function(fn, *, name=None, description=None, input_schema=None)#
Build a ClientTool from a Python callable.
The tool’s name defaults to
fn.__name__. The tool description defaults to the summary-and-body offn’s docstring (everything before the first Google-style section header likeArgs:orReturns:). Per-parameter descriptions are pulled from the docstring’sArgs:section, and can be overridden withtyping.Annotated[T, pydantic.Field(description="...")]orparam: T = pydantic.Field(description="...").- Parameters:
fn (collections.abc.Callable[Ellipsis, Any]) – 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
fnhas 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:
ValueError – If the description cannot be resolved, or if
input_schemais not provided and the signature cannot be automatically converted (e.g. uses*argsor**kwargs).- Return type:
- property name: str#
Tool name surfaced to the LLM.
- Return type:
str
- property spec: roboto.ai.agent_thread.record.ClientToolSpec#
Declarative spec sent to the Roboto backend.
- Return type:
- class roboto.ai.agent_thread.ClientToolResult(/, **data)#
Bases:
pydantic.BaseModelResult of executing a client-side tool.
- Parameters:
data (Any)
- output: dict[str, Any] | None = None#
Structured output returned by the tool.
- runtime_ms: int#
Wall-clock execution time of the tool in milliseconds.
- status: ClientToolResultStatus#
Outcome of the tool execution.
- tool_name: str#
Name of the tool that was executed.
- tool_use_id: str#
Identifier of the tool invocation this result corresponds to.
- class roboto.ai.agent_thread.ClientToolResultStatus#
Bases:
roboto.compat.StrEnumOutcome of executing a client-side tool.
- DECLINED = 'declined'#
- ERROR = 'error'#
- SUCCESS = 'success'#
- class roboto.ai.agent_thread.ClientToolSpec(/, **data)#
Bases:
pydantic.BaseModelDeclarative 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 (Any)
- description: str#
- input_schema: dict[str, Any]#
- name: str#
- class roboto.ai.agent_thread.FeedbackCategory#
Bases:
roboto.compat.StrEnumTaxonomy of feedback categories.
Which categories are valid depends on
sentiment(seecategory_is_valid_for_sentiment()).OTHERis always permitted; whenOTHERis among the selected categories,notesis required.- CORRECT = 'correct'#
- FORMATTING = 'formatting'#
- GOOD_TOOL_USE = 'good_tool_use'#
- HELPFUL = 'helpful'#
- INCOMPLETE = 'incomplete'#
- INCORRECT = 'incorrect'#
- OTHER = 'other'#
- REFUSED_VALID_REQUEST = 'refused_valid_request'#
- SLOW = 'slow'#
- TOOL_FAILURE = 'tool_failure'#
- UNSAFE = 'unsafe'#
- class roboto.ai.agent_thread.FeedbackSentiment#
Bases:
roboto.compat.StrEnumOverall rating direction for a piece of AI-chat feedback.
- NEGATIVE = 'negative'#
- POSITIVE = 'positive'#
- class roboto.ai.agent_thread.ForkAgentThreadRequest(/, **data)#
Bases:
pydantic.BaseModelRequest payload for forking an agent thread at a specific message.
- Parameters:
data (Any)
- message_sequence_num: int#
Highest message sequence number (inclusive) to copy into the new thread.
- class roboto.ai.agent_thread.InvokeSkillSpec(/, **data)#
Bases:
pydantic.BaseModelSpec for invoking a skill as part of a turn trigger.
Embedded in
SendMessageRequestandStartAgentThreadRequest. 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.skillsimport cycle.- Parameters:
data (Any)
- skill_id: str#
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.
- version: int | None = None#
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. UseSkill.set_ai_version()to control the pin separately.
- roboto.ai.agent_thread.NEGATIVE_CATEGORIES: frozenset[FeedbackCategory]#
- roboto.ai.agent_thread.POSITIVE_CATEGORIES: frozenset[FeedbackCategory]#
- exception roboto.ai.agent_thread.RobotoAgentGoalsFailedException(thread_id)#
Bases:
RuntimeErrorRaised by
AgentThread.run()when a goal-bearing turn exhausts its corrective re-prompt budget without satisfying every declared goal.Inherits
RuntimeErrorrather thanRobotoExceptionbecause this is a strictly client-side condition — the session is paused, not errored on the wire — and the project’sRoboto*Exceptionhierarchy 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 opaqueRuntimeErrorrun()used to raise on unexpected statuses.The session is in
AgentThreadStatus.GOALS_FAILED; inspectAgentThread.messagesandAgentThreadRecord.goalsfor detail about which goals failed and why.- Parameters:
thread_id (str)
- thread_id#
- class roboto.ai.agent_thread.SendMessageRequest(/, **data)#
Bases:
pydantic.BaseModelRequest payload for sending a message to an agent thread.
Contains the message content and optional context for the AI assistant.
- Parameters:
data (Any)
- analysis_scope: roboto.ai.core.AnalysisScope | None = None#
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 viasend).
- client_context: roboto.ai.core.ClientViewingContext | None = None#
Optional
ClientViewingContextdescribing what the client was viewing when this message was composed. Wire field isclient_context; the legacycontextalias is accepted during the migration window and will be dropped in a future release.
- client_tools: list[roboto.ai.core.record.ClientToolSpec] | None = None#
Optional client-side tools available for this invocation.
- goals: list[roboto.ai.goals.AgentGoal] | None = None#
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,
messagebecomes optional. Capped atMAX_GOALS_PER_TURNentries (see the constant for rationale).- Type:
Goals declared for this turn. The agent runner enforces achievement
- invoke_skills: list[InvokeSkillSpec] = None#
Skills to invoke as part of this turn, in order. The server fabricates one
LoadSkillTooltool_use+tool_resultpair per entry and appends them to the transcript aftermessage(if any). Whenmessageis 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.
- message: roboto.ai.core.record.AgentMessage | None = None#
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.
- class roboto.ai.agent_thread.StartAgentThreadRequest(/, **data)#
Bases:
pydantic.BaseModelRequest payload for starting a new agent thread.
Contains the initial messages and configuration for creating a new conversation.
- Parameters:
data (Any)
- analysis_scope: roboto.ai.core.AnalysisScope | None = None#
Optional analysis scope for the thread. Delivered to every tool invocation on the server side; individual tools opt in to honoring it.
Nonemeans no scope.
- available_skills: list[AvailableSkillSpec] | None = None#
Explicit set of skills the AI may auto-invoke during this thread, replacing the subscription-derived
load_skillregistry.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_identries 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 atMAX_AVAILABLE_SKILLSentries.Distinct from
invoke_skills:available_skillsconfigures what the AI can reach for, whileinvoke_skillsseeds skill bodies into the opening transcript as a turn trigger. It is configuration, not a trigger — a request carrying onlyavailable_skillsand nomessages/goals/invoke_skillsis still rejected.
- client_context: roboto.ai.core.ClientViewingContext | None = None#
Optional
ClientViewingContextdescribing what the client was viewing when this thread was started. Wire field isclient_context; the legacycontextalias is accepted during the migration window and will be dropped in a future release.
- client_tools: list[roboto.ai.core.record.ClientToolSpec] | None = None#
Optional client-side tools available for this invocation.
- goals: list[roboto.ai.goals.AgentGoal] | None = None#
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,
messagesmay be empty. Capped atMAX_GOALS_PER_TURNentries (see the constant for rationale).- Type:
Goals declared for the first turn. The agent runner enforces achievement
- invoke_skills: list[InvokeSkillSpec] = None#
Skills to invoke at thread start, in order. The server fabricates one
LoadSkillTooltool_use+tool_resultpair per entry and appends them to the transcript after any seededmessages. Whenmessagesis 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.
- messages: list[roboto.ai.core.record.AgentMessage] = None#
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.
- model_profile: str | None = None#
Optional model profile ID for the thread (e.g. ‘standard’, ‘advanced’).
- system_prompt: str | None = None#
Optional system prompt to customize AI assistant behavior.
- visibility: roboto.ai.core.record.ThreadVisibility#
Who may read the resulting thread after it is created.
PRIVATE(the default) restricts reads to the creator and Roboto admins;ORGlets any member of the thread’s org read it and makes the thread visible to org members onPOST /v1/ai/threads/search. The default isPRIVATEso that a thread started viaPOST /v1/ai/threadsdoes not leak to the rest of the org until the caller opts in; threads created through the agent launch flow default toORGinstead, since agents exist to share workflows across teammates.
- class roboto.ai.agent_thread.SubmitFeedbackRequest(/, **data)#
Bases:
pydantic.BaseModelRequest 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 (Any)
- categories: list[FeedbackCategory] = None#
duplicates are dropped and the persisted order is enum-value sort, not request order.
- Type:
Categories describing what was good or bad. Semantically a set
- notes: str | None = None#
Free-text notes. Whitespace-only input is normalised to
Nonebefore persistence. Required whenFeedbackCategory.OTHERis selected.
- sentiment: FeedbackSentiment#
Overall rating direction.
- class roboto.ai.agent_thread.SubmitToolResultsRequest(/, **data)#
Bases:
pydantic.BaseModelRequest payload for submitting client-side tool execution results.
- Parameters:
data (Any)
- client_tools: list[roboto.ai.core.record.ClientToolSpec] | None = None#
Optional updated client-side tools for the next invocation.
- tool_results: list[ClientToolResult]#
Tool results from client-side execution.
- class roboto.ai.agent_thread.ThreadVisibility#
Bases:
roboto.compat.StrEnumRead-scope for an
AgentThreadRecord.Set at thread creation time and immutable for the life of the thread. Import as
roboto.ai.agent_thread.ThreadVisibility.- ORG = '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
ORGthread do not inherit visibility — every fork lands asPRIVATE.
- PRIVATE = 'private'#
Only the creating user (and Roboto admins) may read the thread.
Default for threads created via
POST /v1/ai/threadsso an in-flight experiment does not leak to the rest of the org until the caller opts in.
- class roboto.ai.agent_thread.UserFeedbackRecord(/, **data)#
Bases:
pydantic.BaseModelCustomer-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
AgentFeedbackRecorddirectly.- Parameters:
data (Any)
- categories: list[FeedbackCategory] = None#
Categories describing the feedback. May be empty.
- created: datetime.datetime#
When this feedback was first submitted.
- created_by: str#
User id of the submitter.
- feedback_id: str#
Unique identifier for this feedback entry.
- classmethod from_admin_record(record)#
Project an
AgentFeedbackRecorddown 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_fieldsrather than a hand list of columns: a new submitter-controlled column added to both records flows through automatically, and a new admin-only column onAgentFeedbackRecordis 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 (AgentFeedbackRecord)
- Return type:
- message_sequence_num: int#
Zero-indexed position of the assistant message within the session.
- modified: datetime.datetime#
When the submitter last updated this feedback.
- modified_by: str#
User id of the submitter’s last edit.
- notes: str | None = None#
Free-text notes from the submitter, if any.
- org_id: str#
Org the session belonged to at the time of submission.
- sentiment: FeedbackSentiment#
Overall rating direction.
- thread_id: str#
Session the feedback was submitted against.
- roboto.ai.agent_thread.category_is_valid_for_sentiment(category, sentiment)#
Report whether
categoryis a permitted choice undersentiment.FeedbackCategory.OTHERis always permitted.- Parameters:
category (FeedbackCategory)
sentiment (FeedbackSentiment)
- Return type:
bool
- roboto.ai.agent_thread.client_tool(fn: collections.abc.Callable[Ellipsis, Any], /) ClientTool#
- roboto.ai.agent_thread.client_tool(*, name: str | None = None, description: str | None = None, input_schema: dict[str, Any] | None = None) collections.abc.Callable[[collections.abc.Callable[Ellipsis, Any]], ClientTool]
Decorator that converts a function into a
ClientTool.Usable bare (
@client_tool) or with keyword overrides (@client_tool(description="...")). SeeClientTool.from_function()for how descriptions are resolved.Note
This function is declared with two
typing.overload()stubs above so that type checkers see the decorated name as aClientToolregardless of call form. The overloads carry no runtime behavior; the implementation below handles both shapes.Examples
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: ...