roboto.domain.triggers#
Triggers: fire on platform events or a schedule, filter with a condition, dispatch targets.
A trigger pairs a firing source — a subscription to one or more platform events (fired
at most once per the subscription’s once_per) or a cron schedule — with an optional
condition over the firing’s variable namespace and one or more targets to run on a match.
The event catalog describes what each event type exposes — payload model, namespace
roots, supported once_per values — and drives both save-time validation and evaluation.
Conditions reuse the Condition wire format; target templates
reuse the roboto.templating {{...}} placeholder syntax.
roboto.domain.actions.Trigger is the legacy model of the same thing (one action,
causes/for_each), deprecated and kept only for existing code; it cannot read a
trigger the current model added capabilities to. Trigger here reads them all.
Submodules#
- roboto.domain.triggers.conditions
- roboto.domain.triggers.dispatch
- roboto.domain.triggers.dry_run
- roboto.domain.triggers.namespace
- roboto.domain.triggers.operations
- roboto.domain.triggers.query_templates
- roboto.domain.triggers.record
- roboto.domain.triggers.samples
- roboto.domain.triggers.sources
- roboto.domain.triggers.targets
- roboto.domain.triggers.trigger
- roboto.domain.triggers.validation
Package Contents#
- class roboto.domain.triggers.ConditionLeafTrace(/, **data)#
Bases:
pydantic.BaseModelOne leaf of the trigger’s condition, with the actual value it saw.
- Parameters:
data (Any)
- actual: Any | None = None#
The value the event’s namespace resolved for
field;Nonewhen the field did not resolve (missing entity, missing key).
- comparator: roboto.query.Comparator#
The leaf’s comparator.
- expected: Any | None = None#
The value the condition compares against.
- field: str#
The condition field, as stored on the trigger.
- passed: bool#
Whether this leaf held for the event.
- class roboto.domain.triggers.ConditionMatcher(namespace, default_root)#
Evaluates a trigger condition tree against an event namespace.
Reuses the query
Conditioncomparators unchanged; only the value source differs. Each leaf routes to the namespace root its field targets and matches against that root’s record, so roots hydrate lazily on first reference. A root whose record is missing evaluates to a non-match, soNOT_EXISTSandIS_NULLnever match against an entity that was deleted before evaluation.- Parameters:
namespace (roboto.domain.triggers.namespace.EventNamespace)
default_root (str)
- matches(condition)#
Return whether
conditionholds for the event. ANonecondition always matches.- Parameters:
condition (Optional[roboto.query.ConditionType])
- Return type:
bool
- class roboto.domain.triggers.CreateTriggerRequest(/, **data)#
Bases:
pydantic.BaseModelRequest payload to create a trigger.
The server assigns identity and audit fields, and runs
TriggerValidatorover the cross-field rules (exposed roots,once_perlegality, target placeholders) before persisting.Triggered work runs as the organization’s actions service user; a trigger cannot run its targets as anyone else.
- Parameters:
data (Any)
- condition: roboto.query.ConditionType | None = None#
Optional predicate over the firing’s namespace.
- enabled: bool = True#
Whether the trigger should be active immediately after creation.
- fires_on: roboto.domain.triggers.sources.TriggerSource#
an event subscription or a schedule.
- Type:
What makes the trigger fire
- name: str = None#
Trigger name. Unique within the caller’s organization.
- targets: list[roboto.domain.triggers.targets.TriggerTargetSpec]#
What the trigger dispatches when it fires. At least one.
- class roboto.domain.triggers.DispatchSlot#
One target of one trigger at one dedup token: the unit a dispatch claims.
At most one dispatch ever occupies a slot. It is the dispatch table’s primary key and the vocabulary every dispatch port speaks.
- idempotency_token: str#
- target_id: str#
- trigger_id: str#
- class roboto.domain.triggers.DispatchSlotTrace(/, **data)#
Bases:
pydantic.BaseModelThe state of one target’s dispatch slot at the dry run’s idempotency token.
- Parameters:
data (Any)
- occupied: bool#
Whether a dispatch row occupies the slot (the trigger already fired here).
- result_ref: str | None = None#
What the occupying dispatch produced (invocation id, thread id, Slack ts).
- status: roboto.domain.triggers.dispatch.TriggerDispatchStatus | None = None#
The occupying dispatch’s status, when one exists.
- target_id: str#
The target within the trigger.
- class roboto.domain.triggers.EventNamespace(event, source, *, trigger=None, _records=None)#
Resolves dotted variable paths against a platform event.
The one namespace with three consumers: condition evaluation (whole records via
record()), target template substitution (single paths viaresolve(), satisfying theVariableResolverprotocol), and idempotency projections. Entity-backed roots hydrate through theNamespaceSourceat most once each and are cached for the namespace’s lifetime — includingNoneresults. Theenvelope,changed,tagandscheduleroots are served from the event itself and never touch the source;triggeris served from the bound trigger (seebound_to()) and is otherwise absent.envelopecarries the event’s own fields plus the payload underenvelope.data. The payload is fixed when the event is published, while an entity root reads that entity as it stands at evaluation time: on afile.uploadedevent,envelope.data.file_versionis the version that fired the trigger andfile.versionis the version the file is on when the condition runs. That payload field is optional onfile.uploaded,file.ingestedandfile.metadata_updated, and resolves toNoneon events published before the payload carried it; onlysession.file_addedalways carries it.Payload values are rendered as JSON, so a timestamp under
envelope.datais an ISO-8601 string whileenvelope.timeandschedule.scheduled_foraredatetimeobjects. Conditions compare the two forms alike; a template substitutes each in its own spelling (2026-08-27T09:00:00Zagainst2026-08-27 09:00:00+00:00).- Parameters:
source (NamespaceSource)
trigger (Optional[roboto.domain.triggers.record.TriggerRecord])
_records (Optional[dict[str, Optional[Mapping[str, Any]]]])
- bound_to(trigger)#
A view of this namespace for one trigger, in which
trigger.*resolves.One namespace is shared across every trigger evaluated for an event so each entity hydrates once; the trigger being evaluated is per-trigger state, so it lives on a view rather than on the shared object. The view delegates every other root to the same hydration cache – reading
dataset.namethrough it and through the parent costs one fetch in total.- Parameters:
trigger (roboto.domain.triggers.record.TriggerRecord) – The trigger whose templates and condition are being evaluated.
- Return type:
- get(path)#
Return the value at dotted
path(e.g.dataset.metadata.vehicle_id), orNone.The first path segment names the root; the rest walk nested mappings. Any missing segment yields
None.- Parameters:
path (str)
- Return type:
Any
- record(root)#
Return the whole record for namespace
root, hydrating it at most once.- Parameters:
root (str) – Namespace root to fetch.
envelopeyields the event’s own fields, with the payload fixed at publish time underdata;changedyields the changeset’s put fields;tagyields{"added": [...], "removed": [...]};scheduleandtriggeryield the firing schedule and the bound trigger; any other root delegates to the cachedNamespaceSource.- Returns:
The record as a mapping, or
Nonewhen the source cannot resolve the root.- Return type:
Optional[Mapping[str, Any]]
- resolve(name)#
Return the string form of the value at
namefor template substitution, orNone.- Parameters:
name (str)
- Return type:
Optional[str]
- class roboto.domain.triggers.EventSubscription(/, **data)#
Bases:
_SourceBaseFire when any of the subscribed platform events occurs.
Carries
once_perbecause it only means something here: it names what the event is about that the trigger fires at most once for, and a schedule has no such subject.- Parameters:
data (Any)
- events: list[roboto.domain.platform_events.PlatformEventType]#
Event types the trigger subscribes to. At least one; a condition may only reference namespace roots exposed by every subscribed event.
- fires_for(event_type)#
Return whether an event of
event_typeis one this subscription fires for.- Parameters:
event_type (roboto.domain.platform_events.PlatformEventType)
- Return type:
bool
- once_per: roboto.domain.platform_events.OncePer#
the occurrence, or an entity the event names. Must be legal for every subscribed event type.
- Type:
What the trigger fires at most once per
- type: Literal[TriggerSourceType]#
Discriminator for
TriggerSource.
- class roboto.domain.triggers.InvokeActionTarget(/, **data)#
Bases:
_TargetSpecBaseStored configuration for invoking an action when a trigger fires.
Spec only — dispatch behavior lives server-side. String leaves of
parameter_values,required_inputs,additional_inputs, andinvocation_inputmay contain{{...}}placeholders resolved against the event namespace at dispatch time.An event that names a dataset invokes the action against that dataset, with inputs matched from its files by the file patterns. An event that names no dataset has no files to match: the invocation has no data source and selects its inputs with
invocation_input.- Parameters:
data (Any)
- action: roboto.domain.actions.action_record.ActionReference#
The action to invoke.
ownerdefaults to the trigger’s org when omitted anddigestto the action’s latest version.
- additional_inputs: list[str] | None = None#
Optional extra file patterns passed as invocation inputs beyond the required ones. Only for events that name a dataset; must be empty otherwise.
- compute_requirement_overrides: roboto.domain.actions.action_record.ComputeRequirements | None = None#
Optional compute requirement overrides for the invocation.
- container_parameter_overrides: roboto.domain.actions.action_record.ContainerParameters | None = None#
Optional container parameter overrides for the invocation.
- invocation_input: roboto.domain.actions.invocation_record.InvocationInput | None = None#
Optional query-based input selection (files, topics, sessions) resolved when the invocation runs, e.g.
InvocationInput.from_session_id("{{session.session_id}}"). The way a trigger on an event that names no dataset selects its inputs; may also accompany the file patterns of an event that names one.
- model_config#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- parameter_values: dict[str, Any] = None#
Parameter values passed to the action; string leaves may be templated.
- referenced_placeholders()#
Return every
{{name}}placeholder referenced by this target’s templated fields.- Return type:
set[str]
- required_inputs: list[str] = None#
File patterns (e.g.
**/*.bag) that gate dispatch on the firing event’s files. Only for events that name a dataset; must be empty otherwise.
- target_id: str#
Stable id of this target within its trigger. Part of the dispatch idempotency key: the target’s once-per history is kept under this id, so renaming it (or replacing it with an identical target under a new id) starts a fresh history and the target fires again for subjects the old id already fired for.
- timeout: int | None = None#
Optional invocation timeout override, in minutes.
- type: Literal[TriggerTargetType]#
Discriminator for
TriggerTargetSpec.
- upload_destination: roboto.domain.actions.invocation_record.InvocationUploadDestination | None = None#
Optional destination for the invocation’s output files.
- roboto.domain.triggers.MAX_TRIGGER_NAME_LENGTH = 256#
Maximum trigger name length.
- class roboto.domain.triggers.NamespaceSource#
Bases:
ProtocolLazily hydrates entity-backed namespace roots for an event.
- record_for_root(root, event)#
Load the entity for namespace
rootas a JSON-able mapping.- Parameters:
root (str) – The namespace root to hydrate (
"dataset","file","invocation","event", …). Never a delta or reserved root: the namespace servesenvelope,trigger,schedule,changedandtagitself.event (roboto.domain.platform_events.PlatformEvent) – The event whose subject identifies the entity to load.
- Returns:
The entity as a mapping, or
Nonewheneventcannot resolve it (no such root for this event type, or the entity was deleted between emit and evaluation).- Return type:
Optional[Mapping[str, Any]]
- class roboto.domain.triggers.PlatformEventSample(/, **data)#
Bases:
pydantic.BaseModelOne event type, dereferenced: the envelope, every root it exposes, and the template paths that resolve against them.
- Parameters:
data (Any)
- event: dict[str, Any]#
id, type, time, org, and payload.
- Type:
The event envelope as it would arrive
- event_type: roboto.domain.platform_events.PlatformEventType#
The event type this sample illustrates.
- namespace: dict[str, dict[str, Any]]#
Every namespace root a condition or template may reference for this event type, keyed by root name, with the full record under each. Always includes
envelopeandtrigger; the rest are the catalog’s exposed roots for the type.
- class roboto.domain.triggers.PlatformEventSamplesResponse(/, **data)#
Bases:
pydantic.BaseModelWire shape of
GET /v1/triggers/events/samples: one sample per platform event type.- Parameters:
data (Any)
- samples: dict[roboto.domain.platform_events.PlatformEventType, PlatformEventSample]#
- class roboto.domain.triggers.SampleNamespaceSource#
A
NamespaceSourcethat hydrates every root from the sample scenario.Serves each root the way a real firing does — including
actionas the invocation’s provenance anduploadas the bare transaction id — so a sample carries exactly the roots a trigger would see.- record_for_root(root, event)#
- Parameters:
root (str)
- Return type:
Optional[collections.abc.Mapping[str, Any]]
- class roboto.domain.triggers.Schedule(/, **data)#
Bases:
_SourceBaseFire on a cron schedule, in UTC.
Each scheduled minute fires the trigger once (
once_per='occurrence'over the schedule tick). A missed minute is skipped rather than replayed later, so a delayed schedule never floods targets with backdated firings. Cron expressions are evaluated in UTC; a schedule cannot name a time zone.- Parameters:
data (Any)
- cron: str#
A five-field cron expression (
minute hour day-of-month month day-of-week), evaluated in UTC — e.g.0 9 * * 1for 09:00 UTC every Monday.
- fires_for(event_type)#
Return whether
event_typeis the schedule occurrence this source fires for.- Parameters:
event_type (roboto.domain.platform_events.PlatformEventType)
- Return type:
bool
- property once_per: roboto.domain.platform_events.OncePer#
A schedule always fires once per scheduled minute.
- Return type:
- type: Literal[TriggerSourceType]#
Discriminator for
TriggerSource.
- class roboto.domain.triggers.SendSlackMessageTarget(/, **data)#
Bases:
_TargetSpecBaseStored configuration for posting a Slack message when a trigger fires.
Spec only — dispatch behavior lives server-side. The channel must be on the org’s Slack outbound allowlist at dispatch time.
- Parameters:
data (Any)
- channel_id: str#
Slack channel to post to.
- model_config#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- referenced_placeholders()#
Return every
{{name}}placeholder referenced by this target’s templated text.- Return type:
set[str]
- target_id: str#
Stable id of this target within its trigger; part of the dispatch idempotency key.
- text: str#
Message body; may contain
{{...}}placeholders resolved against the event namespace.
- type: Literal[TriggerTargetType]#
Discriminator for
TriggerTargetSpec.
- class roboto.domain.triggers.StartAgentTarget(/, **data)#
Bases:
_TargetSpecBaseStored configuration for starting an agent thread when a trigger fires.
Spec only — dispatch behavior lives server-side. Each value in
valuesis a template resolved against the event namespace, then handed to the agent’s own variable resolution as a plain value.- Parameters:
data (Any)
- agent_id: str#
The agent definition to launch.
- analysis_scope: roboto.ai.core.AnalysisScope | None = None#
Optional analysis scope for the resulting thread.
- model_config#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- referenced_placeholders()#
Return every
{{name}}placeholder referenced by this target’s templated values.- Return type:
set[str]
- target_id: str#
Stable id of this target within its trigger; part of the dispatch idempotency key.
- type: Literal[TriggerTargetType]#
Discriminator for
TriggerTargetSpec.
- values: dict[str, str] = None#
Agent variable name to a template string resolved against the event namespace.
- visibility: roboto.ai.agent_thread.record.ThreadVisibility#
Visibility of the resulting agent thread.
- roboto.domain.triggers.TRIGGER_NAME_PATTERN = '[\\w\\-]+'#
word characters and hyphens.
- Type:
Legal trigger names
- class roboto.domain.triggers.TargetAcceptanceTrace(/, **data)#
Bases:
pydantic.BaseModelOne target’s prefilter decision.
- Parameters:
data (Any)
- accepted: bool#
Whether the target’s
acceptsprefilter passed.
- reason: str | None = None#
Why the target declined, where determinable (e.g. which required-input pattern had no matching file).
Nonewhen accepted or when no finer reason is known.
- target_id: str#
The target within the trigger.
- target_type: roboto.domain.triggers.targets.TriggerTargetType#
Kind of target.
- class roboto.domain.triggers.Trigger(record, roboto_client=None)#
A trigger: a firing source (event subscriptions or a schedule), an optional condition, and targets.
Triggers created through the older
causes/for_eachAPI (roboto.domain.actions.Trigger) are listed and loaded here too, projected onto this shape and markedengine == "v1"; they accept a narrower set of edits (seeupdate()).Examples
Start an agent whenever a dataset gains a
readytag:>>> from roboto.domain.platform_events import OncePer, PlatformEventType >>> from roboto.domain.triggers import StartAgentTarget, Trigger >>> trigger = Trigger.create( ... name="analyze-ready-datasets", ... targets=[StartAgentTarget(target_id="analyze", agent_id="ag_abc123")], ... events=[PlatformEventType.DatasetTagAdded], ... once_per=OncePer.Occurrence, ... )
Post to Slack every Monday at 09:00 UTC:
>>> from roboto.domain.triggers import SendSlackMessageTarget >>> weekly = Trigger.create( ... name="weekly-status", ... targets=[SendSlackMessageTarget(target_id="post", channel_id="C0123", text="Weekly check-in")], ... schedule="0 9 * * 1", ... )
- Parameters:
roboto_client (Optional[roboto.http.RobotoClient])
- property condition: roboto.query.ConditionType | None#
- Return type:
Optional[roboto.query.ConditionType]
- classmethod create(name, targets, *, events=None, once_per=None, schedule=None, fires_on=None, condition=None, enabled=True, caller_org_id=None, roboto_client=None)#
Create a trigger in the caller’s org.
- Parameters:
name (str) – Trigger name, unique within the org.
targets (list[roboto.domain.triggers.targets.TriggerTargetSpec]) – What to dispatch on a match. At least one.
events (Optional[list[roboto.domain.platform_events.PlatformEventType]]) – Platform event types to subscribe to (with
once_per). At least one.once_per (Optional[roboto.domain.platform_events.OncePer]) – What the trigger fires at most once per; must be legal for every subscribed event.
schedule (Optional[str]) – A cron expression (UTC) to fire on instead of events.
fires_on (Optional[roboto.domain.triggers.sources.TriggerSource]) – The firing source itself, as an alternative to the
events/once_perorscheduleshorthands.condition (Optional[roboto.query.ConditionType]) – Optional predicate over the firing’s namespace.
enabled (bool) – Whether the trigger is active immediately.
caller_org_id (Optional[str]) – Org to create the trigger in. Defaults to the caller’s org.
roboto_client (Optional[roboto.http.RobotoClient]) – Roboto client instance. Uses the default if not provided.
- Returns:
The created trigger.
- Raises:
RobotoInvalidRequestException – A cross-field validation rule fails (e.g. the condition references a root not exposed by every subscribed event).
RobotoConflictException – The name is already taken in the org.
- Return type:
- delete()#
Delete this trigger. Idempotent.
- Return type:
None
- dispatches(limit=100)#
Yield this trigger’s dispatch history, newest first.
A dispatch is one attempt to run one target for one matched event; only matches are recorded, so an empty history means the trigger never fired.
- Parameters:
limit (int) – Page size for the underlying requests.
- Return type:
collections.abc.Generator[roboto.domain.triggers.dispatch.TriggerDispatchRecord, None, None]
- dry_run(event=None, dataset_id=None, file_id=None, invocation_id=None, session_id=None, event_id=None, event_type=None, scheduled_for=None)#
Ask “would this trigger fire?” without dispatching anything.
Provide either a full
eventor exactly one entity reference, from which the server synthesizes an event (event_typeoptionally picks which kind). A schedule-fired trigger takes no reference: passscheduled_forto pick the minute, or nothing for the schedule’s next occurrence. The response is the evaluator’s gate-by-gate trace: subscribed, enabled, condition (with per-leaf actual values), target prefilter, already fired.Examples
>>> trace = trigger.dry_run(dataset_id="ds_abc123") >>> print(trace.verdict)
- Parameters:
event (Optional[roboto.domain.platform_events.PlatformEvent])
dataset_id (Optional[str])
file_id (Optional[str])
invocation_id (Optional[str])
session_id (Optional[str])
event_id (Optional[str])
event_type (Optional[roboto.domain.platform_events.PlatformEventType])
scheduled_for (Optional[datetime.datetime])
- Return type:
- property enabled: bool#
- Return type:
bool
- property engine: str#
"v2", or"v1"for a trigger created through the oldercauses/for_eachAPI.- Type:
Which trigger shape this trigger was created in
- Return type:
str
- property events: List[roboto.domain.platform_events.PlatformEventType] | None#
The subscribed event types, or
Nonefor a schedule-fired trigger.- Return type:
Optional[List[roboto.domain.platform_events.PlatformEventType]]
- property fires_on: roboto.domain.triggers.sources.TriggerSource#
an event subscription or a schedule.
- Type:
What makes the trigger fire
- Return type:
roboto.domain.triggers.sources.TriggerSource
- classmethod from_id(trigger_id, roboto_client=None)#
Load the trigger with the given id, whichever API created it.
- Parameters:
trigger_id (str)
roboto_client (Optional[roboto.http.RobotoClient])
- Return type:
- classmethod from_name(name, owner_org_id=None, roboto_client=None)#
Load the trigger with the given name, whichever API created it. Names are unique within an org.
- Parameters:
name (str)
owner_org_id (Optional[str])
roboto_client (Optional[roboto.http.RobotoClient])
- Return type:
- classmethod list(owner_org_id=None, roboto_client=None)#
Yield every trigger in the org, event-fired and scheduled, newest first, whichever API created it.
- Parameters:
owner_org_id (Optional[str])
roboto_client (Optional[roboto.http.RobotoClient])
- Return type:
collections.abc.Generator[Trigger, None, None]
- property name: str#
- Return type:
str
- property once_per: roboto.domain.platform_events.OncePer#
What the trigger fires at most once per; always
occurrence(one firing per minute) for a schedule.- Return type:
- property org_id: str#
- Return type:
str
- classmethod platform_event_samples(roboto_client=None)#
Fetch a realistic sample of every event type, dereferenced.
Each sample carries the event envelope, every namespace root the type exposes with a full record under it, and the
root.pathlist a condition field or{{ }}placeholder may name. Use it to see what a template will resolve to before writing one.Examples
>>> samples = Trigger.platform_event_samples() >>> samples[PlatformEventType.FileUploaded].paths[:3] ['envelope.id', 'envelope.type', 'envelope.time']
- Parameters:
roboto_client (Optional[roboto.http.RobotoClient])
- Return type:
dict[roboto.domain.platform_events.PlatformEventType, roboto.domain.triggers.samples.PlatformEventSample]
- property record: roboto.domain.triggers.record.TriggerRecord#
- Return type:
- property schedule: str | None#
The cron expression (UTC) the trigger fires on, or
Nonefor an event-fired trigger.- Return type:
Optional[str]
- set_enabled(enabled)#
Enable or disable this trigger.
- Parameters:
enabled (bool)
- Return type:
- property targets: List[roboto.domain.triggers.targets.TriggerTargetSpec]#
- Return type:
List[roboto.domain.triggers.targets.TriggerTargetSpec]
- to_dict()#
Return this trigger’s record as a JSON-able dict.
- Return type:
dict[str, Any]
- property trigger_id: str#
- Return type:
str
- update(*, fires_on=NotSet, events=NotSet, once_per=NotSet, schedule=NotSet, condition=NotSet, targets=NotSet, enabled=NotSet)#
Apply a partial update to this trigger and refresh this instance.
Only provided fields change;
condition=Noneclears the condition. The firing source is replaced whole: passfires_on, or theevents/once_per/scheduleshorthands, which are merged over the current source before being sent. A trigger withengine == "v1"accepts only edits its older shape can express — a single invoke-action target, event types that map onto it,once_peroffileordataset— and rejects the rest with a message naming what it cannot store.- Parameters:
fires_on (Union[roboto.domain.triggers.sources.TriggerSource, roboto.sentinels.NotSetType])
events (Union[List[roboto.domain.platform_events.PlatformEventType], roboto.sentinels.NotSetType])
once_per (Union[roboto.domain.platform_events.OncePer, roboto.sentinels.NotSetType])
schedule (Union[str, roboto.sentinels.NotSetType])
condition (Optional[Union[roboto.query.ConditionType, roboto.sentinels.NotSetType]])
targets (Union[List[roboto.domain.triggers.targets.TriggerTargetSpec], roboto.sentinels.NotSetType])
enabled (Union[bool, roboto.sentinels.NotSetType])
- Return type:
- class roboto.domain.triggers.TriggerDispatchRecord(/, **data)#
Bases:
pydantic.BaseModelWire-transmissible representation of one trigger dispatch.
A dispatch is one attempt to run one target of one trigger for one matched platform event, deduped at the trigger’s
OncePer. The triple (trigger_id,idempotency_token,target_id) is theDispatchSlot; at most one dispatch ever occupies a slot, which is what makes redelivered events safe.- Parameters:
data (Any)
- claimed_at: datetime.datetime#
When the slot was (most recently) claimed.
- dataset_id: str | None = None#
The dataset the subject belongs to (the subject itself for a dataset event), which is what a dataset’s page lists dispatches by.
Nonewhen the subject has no dataset, such as a session or an invocation.
- event_id: str#
Id of the platform event occurrence that most recently claimed this slot.
- event_type: roboto.domain.platform_events.PlatformEventType#
Type of the platform event that matched.
- finalized_at: datetime.datetime | None = None#
When the dispatch reached a terminal status;
Nonewhile claimed.
- idempotency_token: str#
Dedup token derived from the matched event at the trigger’s
once_per({event.type}|{once_per}:{projection}).
- org_id: str#
Organization that owns the trigger.
- result_ref: str | None = None#
an invocation id, an agent thread id, or a Slack message timestamp, per
target_type.- Type:
What a dispatched target produced
- property slot: DispatchSlot#
The slot this dispatch occupies.
- Return type:
- status: TriggerDispatchStatus#
Where this dispatch is in its lifecycle.
- status_detail: str | None = None#
Human-readable detail for
status, e.g. the error a failed target raised.
- subject: str#
The entity the matched platform event was about, as a
roboto://URI; the same value as the event’s ownsubject.
- property subject_uri: roboto.uri.RobotoUri#
subjectas a parsedRobotoUri.- Return type:
- target_id: str#
Which of the trigger’s targets this dispatch ran.
- target_type: roboto.domain.triggers.targets.TriggerTargetType#
Kind of target dispatched.
- trigger_id: str#
Trigger this dispatch belongs to.
- class roboto.domain.triggers.TriggerDispatchStatus#
Bases:
roboto.compat.StrEnumLifecycle state of one dispatch: one attempt to run one target for one matched event.
- Claimed = 'claimed'#
The dispatch slot is claimed and the target is about to run. A claim that neither finalizes nor is reclaimed within the redelivery grace period is presumed dead and may be claimed again, so delivery is at-least-once: a target may run twice for one event.
- Dispatched = 'dispatched'#
The target ran;
TriggerDispatchRecord.result_refpoints at what it produced.
- Failed = 'failed'#
The target raised; a redelivered event may claim the slot again.
- Unknown = 'unknown'#
The claim outlived every redelivery of its event without finalizing, so the outcome cannot be determined. Set by an operational sweep, never reclaimable.
- class roboto.domain.triggers.TriggerDryRunGate(/, **data)#
Bases:
pydantic.BaseModelOne gate’s result in a dry-run trace.
condition_leavesis populated only on theconditiongate,targetsonly ontarget_prefilter, andidempotency_token/dispatchesonly onalready_fired.- Parameters:
data (Any)
- condition_leaves: list[ConditionLeafTrace] | None = None#
Per-leaf results with actual values (
conditiongate only).
- detail: str | None = None#
Plain-English explanation of the outcome.
- dispatches: list[DispatchSlotTrace] | None = None#
Per-target dispatch-slot state at the token (
already_firedgate only).
- gate: TriggerDryRunGateName#
Which gate this is.
- idempotency_token: str | None = None#
The dedup token the event projects onto (
already_firedgate only).
- status: TriggerDryRunGateStatus#
Whether the gate passed, failed, or was short-circuited.
- targets: list[TargetAcceptanceTrace] | None = None#
Per-target prefilter decisions (
target_prefiltergate only).
- class roboto.domain.triggers.TriggerDryRunGateName#
Bases:
roboto.compat.StrEnumThe gates the evaluator runs, in evaluation order.
- AlreadyFired = 'already_fired'#
Is a dispatch slot still claimable at the trigger’s
once_per?
- Condition = 'condition'#
Does the trigger’s condition hold for the event?
- Enabled = 'enabled'#
Is the trigger enabled?
- Subscribed = 'subscribed'#
Is the trigger subscribed to the event’s type?
- TargetPrefilter = 'target_prefilter'#
Does at least one target accept the event (pathspec and precondition gates)?
- class roboto.domain.triggers.TriggerDryRunGateStatus#
Bases:
roboto.compat.StrEnumOutcome of one gate in a dry run.
- Failed = 'failed'#
- NotEvaluated = 'not_evaluated'#
An earlier gate failed, so this one was short-circuited.
- Passed = 'passed'#
- class roboto.domain.triggers.TriggerDryRunRequest(/, **data)#
Bases:
pydantic.BaseModelRequest payload for a trigger dry run.
Provide
event(a fully-formed platform event to evaluate) or a single reference (dataset_id,file_id,invocation_id,session_id,event_id, orscheduled_for), from which the server synthesizes an event. With an entity reference,event_typeoptionally picks which of the trigger’s subscribed event types to synthesize; the default is the trigger’s first subscribed event type compatible with the reference. A schedule-fired trigger needs no reference: the server synthesizes its next scheduled minute.- Parameters:
data (Any)
- dataset_id: str | None = None#
Synthesize an event about this dataset.
- event: roboto.domain.platform_events.PlatformEvent | None = None#
A platform event to evaluate as-is.
- event_id: str | None = None#
Synthesize a platform event about this event (the annotation on your data).
- event_type: roboto.domain.platform_events.PlatformEventType | None = None#
Which subscribed event type to synthesize for an entity reference.
- file_id: str | None = None#
Synthesize an event about this file.
- invocation_id: str | None = None#
Synthesize an event about this invocation.
- scheduled_for: datetime.datetime | None = None#
synthesize the occurrence for this scheduled minute (UTC). With no reference at all, a schedule-fired trigger is dry-run for its next scheduled minute.
- Type:
For a schedule-fired trigger
- session_id: str | None = None#
Synthesize an event about this session.
- class roboto.domain.triggers.TriggerDryRunResponse(/, **data)#
Bases:
pydantic.BaseModelThe structured trace a trigger dry run produces.
Gates appear in evaluation order. The first failed gate is why the trigger would not fire; every gate after it is
not_evaluated.- Parameters:
data (Any)
- event_type: roboto.domain.platform_events.PlatformEventType#
Type of the (given or synthesized) event that was evaluated.
- gates: list[TriggerDryRunGate]#
The gate-by-gate trace, in evaluation order.
- trigger_id: str#
The trigger that was dry-run.
- verdict: str#
One plain-English sentence summarizing the outcome.
- would_fire: bool#
Whether the trigger would dispatch at least one target for this event.
- class roboto.domain.triggers.TriggerRecord(/, **data)#
Bases:
pydantic.BaseModelWire-transmissible representation of a trigger.
A firing source (a platform event subscription or a schedule), an optional condition over the firing’s namespace, and the targets to dispatch on a match. Cross-field rules — exposed roots,
once_perlegality, template placeholders — are enforced when the trigger is saved, byTriggerValidator.Triggered work runs as the organization’s actions service user; a trigger cannot run its targets as anyone else.
- Parameters:
data (Any)
- condition: roboto.query.ConditionType | None = None#
Optional predicate over the firing’s namespace; the trigger fires only when it holds. Same
Conditionwire format the query system uses.
- created: datetime.datetime#
Timestamp when the trigger was created.
- created_by: str#
User ID who created the trigger.
- enabled: bool = True#
Whether the trigger is active.
- engine: str = 'v1'#
"v2"for the events/once_per/targets engine this module models (every trigger, once a deployment has cut over),"v1"for a trigger the oldercauses/for_eachengine still evaluates, projected onto this shape. Server-assigned and read-only; no request model carries it. Defaults to"v1"for a response that omits it, which is what a Roboto deployment older than the field sends.- Type:
Which engine evaluates this trigger
- fires_on: roboto.domain.triggers.sources.TriggerSource#
an
EventSubscription(which also carriesonce_per) or aSchedule.- Type:
What makes the trigger fire
- modified: datetime.datetime#
Timestamp when the trigger was last modified.
- modified_by: str#
User ID who last modified the trigger.
- org_id: str#
Organization that owns the trigger and whose events it sees.
- targets: list[roboto.domain.triggers.targets.TriggerTargetSpec]#
What the trigger dispatches when it fires, in order. At least one; each
target_idis unique within the trigger.
- trigger_id: str#
Unique identifier for the trigger.
- roboto.domain.triggers.TriggerSource#
A trigger’s firing source, discriminated on
type.
- class roboto.domain.triggers.TriggerSourceType#
Bases:
roboto.compat.StrEnumDiscriminator for
TriggerSource.- Events = 'events'#
The trigger fires when a subscribed platform event occurs.
- Schedule = 'schedule'#
The trigger fires on a cron schedule.
- roboto.domain.triggers.TriggerTargetSpec#
A trigger target spec, discriminated on
type.
- class roboto.domain.triggers.TriggerTargetType#
Bases:
roboto.compat.StrEnumThe kind of thing a trigger does when it fires.
- InvokeAction = 'invoke_action'#
Invoke a containerized action.
- SendSlackMessage = 'send_slack_message'#
Post a message to a Slack channel on the org’s allowlist.
- StartAgent = 'start_agent'#
Start an AI agent thread from a saved agent definition.
- class roboto.domain.triggers.TriggerValidator(catalog=DEFAULT_PLATFORM_EVENT_CATALOG)#
Save-time validation for triggers.
Enforces the cross-field rules that need the event catalog: a condition may only reference namespace roots exposed by every event the source fires for,
once_permust be legal for every subscribed event, an action target’s file patterns need a dataset to match against and are themselves required when the firing event’s own file is the action’s input, and every target template placeholder must resolve to a shared exposed root (or a reservedenvelope./trigger.context). A schedule fires for exactly one occurrence type, so the same rules apply to it with that occurrence’s roots.Run before persistence so a trigger that could never fire — or could never resolve its templates — fails loudly with an actionable message instead of silently misbehaving at evaluation time.
- Parameters:
catalog (roboto.domain.platform_events.PlatformEventCatalog)
- validate(*, fires_on, condition, targets)#
Validate the cross-field rules for one trigger’s parts.
- Parameters:
fires_on (roboto.domain.triggers.sources.TriggerSource) – The trigger’s firing source.
condition (Optional[roboto.query.ConditionType]) – Optional predicate over the firing’s namespace.
targets (collections.abc.Sequence[roboto.domain.triggers.targets.TriggerTargetSpec]) – The trigger’s target specs.
- Raises:
ValueError – The first rule that fails, with a message naming the offending field, root, or event.
- Return type:
None
- validate_record(record)#
Validate a full trigger record.
- Raises:
ValueError – Any rule in
validate()fails.- Parameters:
- Return type:
None
- class roboto.domain.triggers.UpdateTriggerRequest(/, **data)#
Bases:
pydantic.BaseModelRequest payload to update a trigger.
Only fields explicitly provided are changed; the
NotSetTypesentinel distinguishes “field omitted” from “field set toNone”. The updated record must still satisfy everyTriggerValidatorrule.- Parameters:
data (Any)
- condition: roboto.query.ConditionType | roboto.sentinels.NotSetType | None#
New condition; explicit
Noneclears it.
- enabled: bool | roboto.sentinels.NotSetType#
New enabled status.
- fires_on: roboto.domain.triggers.sources.TriggerSource | roboto.sentinels.NotSetType#
an event subscription’s events and
once_perchange together, and a trigger may switch between events and a schedule.- Type:
New firing source. Replaces the whole source
- model_config#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- targets: list[roboto.domain.triggers.targets.TriggerTargetSpec] | roboto.sentinels.NotSetType#
New target list. A target whose
target_idis referenced by existing dispatches must keep that id.
- roboto.domain.triggers.iter_query_templates(invocation_input)#
Yield every RoboQL query in
invocation_input, in document order.- Parameters:
invocation_input (collections.abc.Mapping[str, Any])
- Return type:
collections.abc.Iterator[str]
- roboto.domain.triggers.map_query_templates(invocation_input, transform)#
Return
invocation_inputwithtransformapplied to every RoboQL query it holds.- Parameters:
invocation_input (collections.abc.Mapping[str, Any]) – An
InvocationInputin its JSON form, whose top-level values are selectors or lists of them.transform (collections.abc.Callable[[str], str]) – Called with each selector’s query; its result replaces that query.
- Returns:
A copy, shallow below the selectors it rewrites.
- Return type:
dict[str, Any]
- roboto.domain.triggers.platform_event_sample(event_type, catalog=DEFAULT_PLATFORM_EVENT_CATALOG)#
Build the sample for one event type.
The
event,changedandtagroots are built by the sameEventNamespacethat serves them when a trigger fires; the entity roots are exactly the onescatalogexposes for the type.- Parameters:
- Return type:
- roboto.domain.triggers.platform_event_samples(catalog=DEFAULT_PLATFORM_EVENT_CATALOG)#
A sample for every event type in
catalog, in catalog order.- Parameters:
catalog (roboto.domain.platform_events.PlatformEventCatalog)
- Return type:
dict[roboto.domain.platform_events.PlatformEventType, PlatformEventSample]
- roboto.domain.triggers.sample_schedule_trigger()#
The schedule-fired trigger the
schedule.firedsample is evaluated for, so the sample’sscheduleroot carries thecrona template may name.- Return type:
- roboto.domain.triggers.sample_trigger()#
The trigger the sample is evaluated for; what
{{trigger.*}}sees.- Return type:
- roboto.domain.triggers.substitute_query_template(query, resolve)#
Return
querywith each placeholder replaced byresolve’s value for it, escaped in place.Each placeholder is substituted exactly once, and a value is escaped for the literal that encloses it, so a value that itself looks like a template or carries a quote stays data.
- Parameters:
query (str) – A RoboQL query carrying
{{placeholder}}templates.resolve (collections.abc.Callable[[str], str]) – Returns the value for a placeholder name.
- Raises:
ValueError – A placeholder sits outside a string literal, or a value cannot be escaped into the literal it lands in.
- Return type:
str
- roboto.domain.triggers.target_catalog_manifest()#
The kinds of target a trigger can have, as the web UI’s target picker reads them.
target_catalog.jsonin this package is this function’s output, written byscripts/gen_trigger_manifests.pyand drift-checked by a test on each side. Each entry’s body is empty: a target carries no save-time constraint of its own, so the picker offers every type for every event.- Return type:
dict[str, Any]
- roboto.domain.triggers.template_paths(record, prefix)#
Every dotted path a template may reference under
prefix, in document order.Walks nested mappings only. A list is a leaf, because path resolution descends through mappings and stops at anything else:
dataset.tagsis addressable,dataset.tags.0is not.- Parameters:
record (collections.abc.Mapping[str, Any])
prefix (str)
- Return type:
list[str]