roboto.ai.agent
Reusable, parameterized agent definitions.
An agent captures a parameterized StartAgentThreadRequest alongside the variables it declares, so the same workflow (triage, summary, etc.) can be re-invoked against new subjects without re-authoring the request. Variables appear as {{name}} placeholders in any string leaf of the request body and are substituted client-side before the request is sent — unresolved or unknown placeholders raise rather than reach the service.
Submodules
Package Contents
Agent
A reusable, parameterized factory for AgentThread.
An Agent captures a StartAgentThreadRequest body with {{name}} placeholders alongside the TemplateVariable declarations that those placeholders bind to. Invoking the agent substitutes caller-supplied values into the body, runs invoke-time existence checks for typed values (dataset ids, device ids), and starts a session via the same code path as AgentThread.start().
The wrapper is to AgentRecord what Action is to ActionRecord: the record carries the wire-shape data, this class carries the behaviors.
Parameters
roboto_client Optional[roboto.Properties
Agent.agent_id
Platform-issued agt_<short> handle. Stable across renames.
Agent.create()
Persist a new agent in the caller’s organization.
The platform fills agent_id, org_id, created, created_by, modified, and modified_by from the caller’s identity. Every other field comes from this method’s arguments.
Parameters
name strHuman-readable display name. Unique per (org_id, name); a second agent with the same name in the same org is rejected with RobotoConflictException.
request_template roboto.The StartAgentThreadRequest to clone at invoke time. Any string leaf may carry {{name}} placeholders; every referenced placeholder must appear in variables (and vice versa).
variables Optional[collections.TemplateVariable declarations. The set of names here must equal the set of placeholder names referenced anywhere in request_template; a mismatch fails server-side validation with a 400.
description Optional[str]Free-form text rendered on the agent’s detail and library pages.
caller_org_id Optional[str]Organization to create the agent in. If omitted and the caller belongs to exactly one organization, that organization is used; required when the caller belongs to multiple organizations.
roboto_client Optional[roboto.Optional RobotoClient instance. If omitted, the default client configuration is used.
Raises
An agent with the same name already exists in the org.
request_template and variables disagree about the placeholder set, or a variable name is invalid.
The caller lacks permission to create agents in the target organization.
Usage
Create an agent with one dataset-typed variable:
from roboto.ai.agent import Agent, TemplateVariable, TemplateVariableType
from roboto.ai.agent_thread import StartAgentThreadRequest, AgentMessage
request_template = StartAgentThreadRequest(
messages=[AgentMessage.text("Triage dataset {{dataset_id}}.")],
)
agent = Agent.create(
name="triage",
request_template=request_template,
variables=[
TemplateVariable(name="dataset_id", type=TemplateVariableType.DATASET_ID),
],
description="Apply the triage label vocabulary to a dataset.",
)Agent.delete()
Permanently delete this agent.
Sessions previously launched from this agent are unaffected — their created_from_agent_id references this agent’s id independent of any foreign key, so they remain readable. Creating a new agent with the same name in the same org is allowed after deletion.
Raises
The agent has already been deleted.
The caller is not a member of this agent’s org_id.
Return type
Usage
agent = Agent.from_name("retired_triage")
agent.delete()Properties
Agent.description
Free-form text rendered on the agent’s detail and library pages.
Agent.for_org()
Iterate every Agent declared in an organization.
Yields agents newest-first (by created) and paginates transparently; callers consume the generator without worrying about next_token.
Parameters
org_id Optional[str]Organization to list agents for. If omitted and the caller belongs to exactly one organization, that organization is used.
roboto_client Optional[roboto.Optional RobotoClient; defaults to the ambient configuration.
Yields
Agent instances, one per row, in newest-first order.
Return type
Usage
Print every agent’s name:
for agent in Agent.for_org():
print(agent.name)Count agents in a specific org:
count = sum(1 for _ in Agent.for_org(org_id="og_abc123"))Agent.from_id()
Load an Agent by its canonical id.
agent_id is platform-unique, so the SDK does not need the caller to declare which org the agent lives in — the route looks up the record and authorizes the caller against the record’s org_id.
Parameters
agent_id strThe platform-issued agt_<short> identifier.
roboto_client Optional[roboto.Optional RobotoClient; defaults to the ambient configuration.
Raises
The agent does not exist or belongs to an organization the caller cannot read.
Usage
agent = Agent.from_id("agt_abc123")Agent.from_name()
Load an Agent by its (org_id, name) handle.
Mirrors from_name(): name + owning org are jointly unique, so this returns at most one agent. Unlike from_id() (which derives the org from the looked-up record), name lookup needs the org up-front and goes through the X-Roboto-Resource-Owner-Id header. agent_id (the canonical handle) stays stable across renames, so a script that pins by name follows renames; a script that pins by id does not.
Parameters
name strThe agent’s name.
roboto_client Optional[roboto.Optional RobotoClient; defaults to the ambient configuration.
owner_org_id Optional[str]Organization that owns the agent. If omitted and the caller belongs to one organization, that organization is used.
Raises
No agent with that name exists in the resolved organization.
Usage
agent = Agent.from_name("triage")Agent.launch()
Resolve placeholders and start an AgentThread.
The platform substitutes values into request_template, runs launch-time existence checks on typed values (DATASET_ID / DEVICE_ID), and creates a thread via the same code path as a bare AgentThread.start(). The resulting thread is owned by this agent’s org_id (not the caller’s default org), and its created_from_agent_id is stamped with this agent’s agent_id so the agent detail page can list “threads launched from here”.
Parameters
values Optional[dict[str, str]]Variable name to caller-supplied value. Keys must match the names declared in variables; values are coerced to str before splicing into placeholders. Omit when every declared variable carries a default.
visibility roboto.ThreadVisibility for the new thread. Defaults to ORG because agents exist to share workflows; the caller passes PRIVATE to opt out per launch. Overrides whatever the authored request_template carries.
analysis_scope Optional[roboto.Optional AnalysisScope for the new thread. When provided, it is zipper-merged onto whatever the authored request_template carries: each dimension the caller set wins, and the rest inherit from the template. When omitted, the template’s scope (usually none) is left untouched.
Returns
An AgentThread wrapping the freshly created thread. The thread is fully hydrated (messages, status, continuation token) and ready for AgentThread.run() or AgentThread.events().
Raises
values is missing a required variable, references an unknown variable, or a typed value (DATASET_ID / DEVICE_ID) names a resource that does not exist in the agent’s org.
This agent has been deleted since the wrapper was loaded.
The caller is not a member of this agent’s org_id or that org is not on a premium plan.
Usage
agent = Agent.from_name("triage")
thread = agent.launch(values={"dataset_id": "ds_abc123"})
thread.run()Properties
Agent.modified
Wall-clock time of the most recent successful update.
Agent.modified_by
User id who applied the most recent update; equals created_by for records never edited since creation.
Agent.record
Underlying AgentRecord.
Wire shape used in API requests; may evolve over time. Prefer the public Agent API unless you need direct record access.
Agent.request_template
The StartAgentThreadRequest cloned at invoke time.
Agent.to_dict()
Return the JSON-serializable form of the underlying record.
Return type
Agent.update()
Apply a partial update.
Each parameter defaults to NotSet so omitting a field leaves it untouched on the server, while passing None for description clears it. request_template and variables are co-validated server-side after the merge: the post-update placeholder set must equal the post-update variable set, even if only one of the two fields was supplied.
Parameters
name Union[str, roboto.Replace the display name. Subject to the same (org_id, name) uniqueness as create().
description Union[Optional[str], roboto.Replace the description. Pass None to clear; omit to leave unchanged.
request_template Union[roboto.Replace the StartAgentThreadRequest.
variables Union[collections.Replace the variable declarations.
Raises
name collides with another agent in the same org.
The post-update placeholder set disagrees with the post-update variable set.
The agent has been deleted.
The caller is not a member of this agent’s org_id.
Usage
agent.update(description="Triages a dataset against the v2 label vocab.")Clear the description:
agent.update(description=None)Properties
Agent.variables
TemplateVariable declarations. The set of names here equals the set of placeholders referenced in request_template.
AgentRecord
Bases: pydantic.BaseModel
A pre-filled StartAgentThreadRequest plus declared variables.
An AgentRecord captures most of what an AgentThread needs to start - system prompt, model profile, seeded messages, declared goals - and leaves a small set of named holes that callers must fill at invoke time. The canonical example is a triage agent whose goal carries a fixed label_vocabulary but a {{dataset.id}} placeholder, so the same agent can be re-run against many datasets without re-declaring the vocabulary.
The record’s main invariant - enforced by _validate_variables_match_placeholders() - is that the set of {{...}} placeholders found anywhere in request_template equals exactly {v.name for v in variables}. A mismatch fails at save time so stale invoke forms can’t paper over typos.
Parameters
data AnyAttributes
AgentRecord.agent_id
Canonical handle. Generated server-side (agt_<short>); stable across renames.
AgentRecord.description
Free-form description rendered on the agents list and detail pages.
AgentRecord.modified
Wall-clock time of the most recent successful update.
AgentRecord.modified_by
User id who applied the most recent update; equals created_by on records that have not been edited since creation.
AgentRecord.name
Human-readable display name. Mutable. Unique per (org_id, name) - enforced at the persistence layer, not on the record.
AgentRecord.org_id
Organization that owns the agent. All CRUD and invoke calls must come from a member of this org.
AgentRecord.request_template
The body that will be cloned and resolved into a real StartAgentThreadRequest at invoke time. Any string leaf may contain {{name}} placeholders; non-string fields cannot be templated, because substitution visits string leaves only.
AgentRecord.variables
Declared variables. The set of names here must equal the set of placeholder names parsed from request_template.
AgentResolutionError
Bases: ValueError
Base class for resolver-raised errors. Routes map subclasses to 4xx.
CreateAgentRequest
Bases: pydantic.BaseModel
Wire payload for POST /v1/ai/agents.
The server fills AgentRecord.agent_id, org_id, created_by, created, modified, and modified_by from the caller’s identity; everything else comes from this request.
Parameters
data AnyAttributes
CreateAgentRequest.description
CreateAgentRequest.name
CreateAgentRequest.request_template
CreateAgentRequest.variables
LaunchAgentRequest
Bases: pydantic.BaseModel
Wire payload for POST /v1/ai/agents/<agent_id>/launch.
The route resolves the named agent, substitutes values into its body, and starts a new AgentThread whose visibility comes from visibility and whose created_from_agent_id points back at the source agent.
Parameters
data AnyAttributes
LaunchAgentRequest.analysis_scope
Optional AnalysisScope for the resulting thread. When provided, it is zipper-merged onto whatever the agent’s request_template.analysis_scope field carries: each dimension the caller set wins, and the rest inherit from the template. When None, the authored template’s scope (usually none) is left untouched.
LaunchAgentRequest.values
Variable name to caller-supplied value. Keys must match declared TemplateVariable names; values are coerced to str before being spliced into placeholders.
LaunchAgentRequest.visibility
Visibility of the resulting AgentThread. Invoke-time wins: this value overrides whatever the agent’s request_template.visibility field carries. Agents cannot pin visibility — authors who need to convey recommended visibility do so in the agent’s description. Defaults to ORG because agents exist to share workflows across teammates; PRIVATE is an explicit opt-out per invocation.
TemplateVariable
Bases: pydantic.BaseModel
A named slot in an AgentRecord that must be filled before the agent can be invoked.
Variables are declared up-front rather than inferred from the body so that the invoke UI can render typed inputs (dataset pickers, etc.) and so that a typo in the body ({{dataste.id}}) surfaces as a save-time validation error rather than a silent extra prompt at invoke time. The declared set and the set of placeholders parsed from the body must match exactly - see AgentRecord._validate_variables_match_placeholders().
Parameters
data AnyAttributes
TemplateVariable.collection_content_type
Only meaningful when type is TemplateVariableType.COLLECTION_ID: constrains the invoke-page collection picker to collections holding this resource type (e.g. event collections for a create-events goal). None leaves the picker unconstrained. Must be None for every other variable type — see _validate_resolvable().
TemplateVariable.default
Default value substituted when the caller omits the variable. Coerced to str; types are a UI concern.
TemplateVariable.description
Human-readable explanation rendered next to the input on the invoke page.
TemplateVariable.name
Lookup key for substitution. Must match VARIABLE_NAME_RE; see that pattern for the dotted-name namespace convention. Two variables sharing a prefix (dataset.id + dataset.name) without an upstream expander produce two unlinked inputs at invoke time — that’s a UI-authoring footgun, not an SDK contract.
TemplateVariable.required
If True the resolver raises UnresolvedAgentVariablesError when no value is supplied and no default is set.
TemplateVariable.type
UI hint for the invoke page. See TemplateVariableType.
TemplateVariableType
Bases: roboto.compat.StrEnum
How a variable’s value is interpreted when an agent is launched.
Substitution itself is type-agnostic: every value is spliced in as a string. The type drives two things a caller can observe — the Roboto web app picks a richer input control (dataset picker, device picker), and a typed value is checked for existence when the agent is launched, so a bad id is rejected up front rather than inside the agent’s first tool call.
Attributes
TemplateVariableType.COLLECTION_ID
A Roboto collection identifier. UI renders a collection picker; invoke-time validator asserts the collection exists in the caller’s org.
TemplateVariableType.DATASET_ID
A Roboto dataset identifier. UI renders a dataset picker; invoke-time validator asserts the dataset exists in the caller’s org.
TemplateVariableType.DEVICE_ID
A Roboto device identifier. UI renders a device picker; invoke-time validator asserts the device is registered in the caller’s org.
TemplateVariableType.STRING
Free-form text. The default; renders as a plain text input. No existence check (no entity to check against).
UnknownAgentVariablesError
Bases: AgentResolutionError
Caller supplied values for variables the agent no longer declares — almost always a stale invoke form. Mapped to 400 so the UI can refetch.
Parameters
names list[str]Attributes
UnknownAgentVariablesError.names
names #UnresolvedAgentVariablesError
Bases: AgentResolutionError
Required variables had no supplied value and no default. Mapped to 400 with the names so the invoke page can highlight the empty inputs.
Parameters
names list[str]Attributes
UnresolvedAgentVariablesError.names
names #UpdateAgentRequest
Bases: pydantic.BaseModel
Wire payload for PUT /v1/ai/agents/<agent_id>.
Uses the NotSetType sentinel to distinguish “field omitted” from “field explicitly set to None” so partial updates don’t accidentally null out unrelated fields.
Parameters
data AnyAttributes
UpdateAgentRequest.description
UpdateAgentRequest.model_config
model_config #Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
UpdateAgentRequest.name
UpdateAgentRequest.request_template
request_template roboto.UpdateAgentRequest.variables
extract_placeholders()
Return every {{name}} placeholder referenced anywhere in body.
Walks the JSON form of the request rather than the Pydantic model so the traversal is type-agnostic - placeholders inside label_vocabulary values, message text, system prompt, etc. all get picked up without needing per-field logic. Only string values are scanned; dict keys are intentionally ignored so key-collision footguns never arise.
Parameters
Return type
resolve_agent()
Substitute values into agent.request_template and return a fully-validated StartAgentThreadRequest.
Walks the body’s JSON form swapping every {{name}} occurrence in a string leaf. Embedded substitution is supported. Dict keys are never touched — placeholder syntax in keys is rejected at save time.
Parameters
values dict[str, str]Raises
values contains keys not declared on the agent (typically a stale invoke form).
a required variable has neither a supplied value nor a default; carries the offending names.
pydantic.ValidationErrorthe substituted body failed StartAgentThreadRequest validation — e.g. a resolved value doesn’t match a field-level regex or enum.