Skip to content
Roboto
Esc
↑↓navigate↵open⌘Jpreview
On this page

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

Package Contents

ActionInvocationSpec

class roboto.domain.triggers.ActionInvocationSpec(/, **data)#View Source

Bases: pydantic.BaseModel

How to run an action: which action, its parameters, overrides, and input selectors.

The part of an invoke-action target that says nothing about when it runs, shared by InvokeActionTarget and anything else that stores an action invocation to run later, such as an ingestion rule. String leaves of parameter_values and invocation_input may contain {{...}} placeholders resolved against the event namespace at dispatch time.

Parameters

data Any

Attributes

ActionInvocationSpec.action

The action to invoke. owner defaults to the trigger’s org when omitted and digest to the action’s latest version.

ActionInvocationSpec.compute_requirement_overrides

compute_requirement_overrides roboto.domain.actions.action_record.ComputeRequirements | None = None #

Optional compute requirement overrides for the invocation.

ActionInvocationSpec.container_parameter_overrides

container_parameter_overrides roboto.domain.actions.action_record.ContainerParameters | None = None #

Optional container parameter overrides for the invocation.

ActionInvocationSpec.invocation_input

Optional query-based input selection (files, topics, sessions) resolved when the invocation runs, e.g. InvocationInput.file_query('tags CONTAINS "{{event.name}}"'). 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.

ActionInvocationSpec.model_config

model_config #

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

ActionInvocationSpec.parameter_values

parameter_values dict[str, Any] = None #

Parameter values passed to the action; string leaves may be templated.

ActionInvocationSpec.referenced_placeholders()

referenced_placeholders()#View Source

Return every {{name}} placeholder referenced by this spec’s templated fields.

Return type

set[str]

Attributes

ActionInvocationSpec.timeout

timeout int | None = None #

Optional invocation timeout override, in minutes.

ActionInvocationSpec.upload_destination

Optional destination for the invocation’s output files.

ConditionLeafTrace

class roboto.domain.triggers.ConditionLeafTrace(/, **data)#View Source

Bases: pydantic.BaseModel

One leaf of the trigger’s condition, with the actual value it saw.

Parameters

data Any

Attributes

ConditionLeafTrace.actual

actual Any | None = None #

The value the event’s namespace resolved for field; None when the field did not resolve (missing entity, missing key).

ConditionLeafTrace.comparator

The leaf’s comparator.

ConditionLeafTrace.expected

expected Any | None = None #

The value the condition compares against.

ConditionLeafTrace.field

field str #

The condition field, as stored on the trigger.

ConditionLeafTrace.passed

passed bool #

Whether this leaf held for the event.

ConditionMatcher

class roboto.domain.triggers.ConditionMatcher(namespace, default_root)#View Source

Evaluates a trigger condition tree against an event namespace.

Reuses the query Condition comparators 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, so NOT_EXISTS and IS_NULL never match against an entity that was deleted before evaluation.

Parameters

ConditionMatcher.matches()

matches(condition)#View Source

Return whether condition holds for the event. A None condition always matches.

Parameters

condition Optional[roboto.query.ConditionType]

Return type

bool

CreateTriggerRequest

class roboto.domain.triggers.CreateTriggerRequest(/, **data)#View Source

Bases: pydantic.BaseModel

Request payload to create a trigger.

The server assigns identity and audit fields, and runs TriggerValidator over the cross-field rules (exposed roots, once_per legality, 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

Attributes

CreateTriggerRequest.condition

condition roboto.query.ConditionType | None = None #

Optional predicate over the firing’s namespace.

CreateTriggerRequest.enabled

enabled bool = True #

Whether the trigger should be active immediately after creation.

CreateTriggerRequest.fires_on

What makes the trigger fire: an event subscription or a schedule.

CreateTriggerRequest.name

name str = None #

Trigger name. Unique within the caller’s organization.

CreateTriggerRequest.targets

What the trigger dispatches when it fires. At least one.

DispatchSlot

class roboto.domain.triggers.DispatchSlot#View Source

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.

Attributes

DispatchSlot.idempotency_token

idempotency_token str #

DispatchSlot.target_id

target_id str #

DispatchSlot.trigger_id

trigger_id str #

DispatchSlotTrace

class roboto.domain.triggers.DispatchSlotTrace(/, **data)#View Source

Bases: pydantic.BaseModel

The state of one target’s dispatch slot at the dry run’s idempotency token.

Parameters

data Any

Attributes

DispatchSlotTrace.occupied

occupied bool #

Whether a dispatch row occupies the slot (the trigger already fired here).

DispatchSlotTrace.result_ref

result_ref str | None = None #

What the occupying dispatch produced (invocation id, thread id, Slack ts).

DispatchSlotTrace.status

The occupying dispatch’s status, when one exists.

DispatchSlotTrace.target_id

target_id str #

The target within the trigger.

EventNamespace

class roboto.domain.triggers.EventNamespace(event, source, *, trigger=None, _records=None)#View Source

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 via resolve(), satisfying the VariableResolver protocol), and idempotency projections. Entity-backed roots hydrate through the NamespaceSource at most once each and are cached for the namespace’s lifetime — including None results. The envelope, changed, tag and schedule roots are served from the event itself and never touch the source; trigger is served from the bound trigger (see bound_to()) and is otherwise absent.

envelope carries the event’s own fields plus the payload under envelope.data. The payload is fixed when the event is published, while an entity root reads that entity as it stands at evaluation time: on a file.uploaded event, envelope.data.file_version is the version that fired the trigger and file.version is the version the file is on when the condition runs. That payload field is optional on file.uploaded, file.ingested and file.metadata_updated, and resolves to None on events published before the payload carried it.

Payload values are rendered as JSON, so a timestamp under envelope.data is an ISO-8601 string while envelope.time and schedule.scheduled_for are datetime objects. Conditions compare the two forms alike; a template substitutes each in its own spelling (2026-08-27T09:00:00Z against 2026-08-27 09:00:00+00:00).

Parameters

_records Optional[dict[str, Optional[Mapping[str, Any]]]]

EventNamespace.bound_to()

bound_to(trigger)#View Source

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.name through it and through the parent costs one fetch in total.

Parameters

The trigger whose templates and condition are being evaluated.

Return type

EventNamespace.get()

get(path)#View Source

Return the value at dotted path (e.g. dataset.metadata.vehicle_id), or None.

The first path segment names the root; the rest walk nested mappings. Any missing segment yields None.

Parameters

path str

Return type

Any

EventNamespace.record()

record(root)#View Source

Return the whole record for namespace root, hydrating it at most once.

Parameters

root str

Namespace root to fetch. envelope yields the event’s own fields, with the payload fixed at publish time under data; changed yields the changeset’s put fields; tag yields {"added": [...], "removed": [...]}; schedule and trigger yield the firing schedule and the bound trigger; any other root delegates to the cached NamespaceSource.

Returns

Optional[Mapping[str, Any]]

The record as a mapping, or None when the source cannot resolve the root.

EventNamespace.resolve()

resolve(name)#View Source

Return the string form of the value at name for template substitution, or None.

Parameters

name str

Return type

Optional[str]

EventSubscription

class roboto.domain.triggers.EventSubscription(/, **data)#View Source

Bases: _SourceBase

Fire when any of the subscribed platform events occurs.

Carries once_per because 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

Attributes

EventSubscription.events

Event types the trigger subscribes to. At least one; a condition may only reference namespace roots exposed by every subscribed event.

EventSubscription.fires_for()

fires_for(event_type)#View Source

Return whether an event of event_type is one this subscription fires for.

Return type

bool

Attributes

EventSubscription.once_per

What the trigger fires at most once per: the occurrence, or an entity the event names. Must be legal for every subscribed event type.

EventSubscription.type

type Literal[TriggerSourceType] #

Discriminator for TriggerSource.

InvokeActionTarget

class roboto.domain.triggers.InvokeActionTarget(/, **data)#View Source

Bases: ActionInvocationSpec, _TargetSpecBase

Stored configuration for invoking an action when a trigger fires.

Spec only — dispatch behavior lives server-side. The ActionInvocationSpec fields say how to run the action; this class adds the target’s identity and its file patterns. String leaves of required_inputs and additional_inputs may contain {{...}} placeholders, as the spec’s may.

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

Attributes

InvokeActionTarget.additional_inputs

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.

InvokeActionTarget.from_invocation()

classmethod from_invocation(invocation, *, target_id, required_inputs=None, additional_inputs=None)#View Source

A target that runs invocation, with the given identity and file patterns.

Parameters

target_id str
required_inputs Optional[list[str]]
additional_inputs Optional[list[str]]

InvokeActionTarget.invocation()

invocation()#View Source

How this target runs its action, without its identity or file patterns.

Attributes

InvokeActionTarget.model_config

model_config #

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

InvokeActionTarget.referenced_placeholders()

referenced_placeholders()#View Source

Return every {{name}} placeholder referenced by this target’s templated fields.

Return type

set[str]

Attributes

InvokeActionTarget.required_inputs

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.

InvokeActionTarget.target_id

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.

InvokeActionTarget.type

type Literal[TriggerTargetType] #

Discriminator for TriggerTargetSpec.

MAX_TRIGGER_NAME_LENGTH

roboto.domain.triggers.MAX_TRIGGER_NAME_LENGTH = 256#View Source

Maximum trigger name length.

ManagedBy

class roboto.domain.triggers.ManagedBy(/, **data)#View Source

Bases: pydantic.BaseModel

The owner of a trigger whose definition is managed by something other than the org’s members.

No managed trigger can be deleted, or have its definition changed, through the triggers API. Org members may enable or disable a system-managed trigger. A trigger owned by an ingestion rule may not be enabled, disabled, edited or deleted directly: change the rule instead, e.g. turn its auto-ingest off. An org has at most one trigger per owner.

Parameters

data Any

Attributes

ManagedBy.id

id str #

Which one: for ManagedByKind.System, the platform feature’s key (e.g. "session_metrics"); for ManagedByKind.IngestionRule, the rule’s id.

ManagedBy.kind

What kind of thing manages the trigger.

ManagedBy.model_config

model_config #

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

ManagedByKind

class roboto.domain.triggers.ManagedByKind#View Source

Bases: roboto.compat.StrEnum

What kind of thing in Roboto manages a trigger.

Attributes

ManagedByKind.IngestionRule

IngestionRule = 'ingestion_rule' #

An ingestion rule owns the trigger and is its only edit surface.

ManagedByKind.System

System = 'system' #

Roboto installed the trigger to run a platform feature.

NamespaceSource

class roboto.domain.triggers.NamespaceSource#View Source

Bases: Protocol

Lazily hydrates entity-backed namespace roots for an event.

NamespaceSource.record_for_root()

record_for_root(root, event)#View Source

Load the entity for namespace root as a JSON-able mapping.

Parameters

root str

The namespace root to hydrate ("dataset", "file", "invocation", "event", …). Never a delta or reserved root: the namespace serves envelope, trigger, schedule, changed and tag itself.

The event whose subject identifies the entity to load.

Returns

Optional[Mapping[str, Any]]

The entity as a mapping, or None when event cannot resolve it (no such root for this event type, or the entity was deleted between emit and evaluation).

PlatformEventSample

class roboto.domain.triggers.PlatformEventSample(/, **data)#View Source

Bases: pydantic.BaseModel

One event type, dereferenced: the envelope, every root it exposes, and the template paths that resolve against them.

Parameters

data Any

Attributes

PlatformEventSample.event

event dict[str, Any] #

The event envelope as it would arrive: id, type, time, org, and payload.

PlatformEventSample.event_type

The event type this sample illustrates.

PlatformEventSample.namespace

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 envelope and trigger; the rest are the catalog’s exposed roots for the type.

PlatformEventSample.paths

paths list[str] #

Every root.path a {{ }} placeholder or condition field may name, in the order the roots and their fields appear in namespace.

PlatformEventSamplesResponse

class roboto.domain.triggers.PlatformEventSamplesResponse(/, **data)#View Source

Bases: pydantic.BaseModel

Wire shape of GET /v1/triggers/events/samples: one sample per platform event type.

Parameters

data Any

Attributes

PlatformEventSamplesResponse.samples

SampleNamespaceSource

class roboto.domain.triggers.SampleNamespaceSource#View Source

A NamespaceSource that hydrates every root from the sample scenario.

Serves each root the way a real firing does — including action as the invocation’s provenance and upload as the bare transaction id — so a sample carries exactly the roots a trigger would see.

SampleNamespaceSource.record_for_root()

record_for_root(root, event)#View Source

Return type

Optional[collections.abc.Mapping[str, Any]]

Schedule

class roboto.domain.triggers.Schedule(/, **data)#View Source

Bases: _SourceBase

Fire 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

Attributes

Schedule.cron

cron str #

A five-field cron expression (minute hour day-of-month month day-of-week), evaluated in UTC — e.g. 0 9 * * 1 for 09:00 UTC every Monday.

Schedule.fires_for()

fires_for(event_type)#View Source

Return whether event_type is the schedule occurrence this source fires for.

Return type

bool

Properties

Schedule.once_per

A schedule always fires once per scheduled minute.

Attributes

Schedule.type

type Literal[TriggerSourceType] #

Discriminator for TriggerSource.

SendSlackMessageTarget

class roboto.domain.triggers.SendSlackMessageTarget(/, **data)#View Source

Bases: _TargetSpecBase

Stored 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

Attributes

SendSlackMessageTarget.channel_id

channel_id str #

Slack channel to post to.

SendSlackMessageTarget.model_config

model_config #

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

SendSlackMessageTarget.referenced_placeholders()

referenced_placeholders()#View Source

Return every {{name}} placeholder referenced by this target’s templated text.

Return type

set[str]

Attributes

SendSlackMessageTarget.target_id

target_id str #

Stable id of this target within its trigger; part of the dispatch idempotency key.

SendSlackMessageTarget.text

text str #

Message body; may contain {{...}} placeholders resolved against the event namespace.

SendSlackMessageTarget.type

type Literal[TriggerTargetType] #

Discriminator for TriggerTargetSpec.

StartAgentTarget

class roboto.domain.triggers.StartAgentTarget(/, **data)#View Source

Bases: _TargetSpecBase

Stored configuration for starting an agent thread when a trigger fires.

Spec only — dispatch behavior lives server-side. Each value in values is a template resolved against the event namespace, then handed to the agent’s own variable resolution as a plain value.

Parameters

data Any

Attributes

StartAgentTarget.agent_id

agent_id str #

The agent definition to launch.

StartAgentTarget.analysis_scope

analysis_scope roboto.ai.core.AnalysisScope | None = None #

Optional analysis scope for the resulting thread.

StartAgentTarget.model_config

model_config #

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

StartAgentTarget.referenced_placeholders()

referenced_placeholders()#View Source

Return every {{name}} placeholder referenced by this target’s templated values.

Return type

set[str]

Attributes

StartAgentTarget.target_id

target_id str #

Stable id of this target within its trigger; part of the dispatch idempotency key.

StartAgentTarget.type

type Literal[TriggerTargetType] #

Discriminator for TriggerTargetSpec.

StartAgentTarget.values

values dict[str, str] = None #

Agent variable name to a template string resolved against the event namespace.

StartAgentTarget.visibility

Visibility of the resulting agent thread.

TRIGGER_NAME_PATTERN

roboto.domain.triggers.TRIGGER_NAME_PATTERN = '[\\w\\-]+'#View Source

Legal trigger names: word characters and hyphens.

TargetAcceptanceTrace

class roboto.domain.triggers.TargetAcceptanceTrace(/, **data)#View Source

Bases: pydantic.BaseModel

One target’s prefilter decision.

Parameters

data Any

Attributes

TargetAcceptanceTrace.accepted

accepted bool #

Whether the target’s accepts prefilter passed.

TargetAcceptanceTrace.reason

reason str | None = None #

Why the target declined, where determinable (e.g. which required-input pattern had no matching file). None when accepted or when no finer reason is known.

TargetAcceptanceTrace.target_id

target_id str #

The target within the trigger.

TargetAcceptanceTrace.target_type

Kind of target.

Trigger

class roboto.domain.triggers.Trigger(record, roboto_client=None)#View Source

A trigger: a firing source (event subscriptions or a schedule), an optional condition, and targets.

Triggers created through the older causes/for_each API (roboto.domain.actions.Trigger) are listed and loaded here too, projected onto this shape and marked engine == "v1"; they accept a narrower set of edits (see update()).

Usage

Start an agent whenever a dataset gains a ready tag:

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",
)

Properties

Trigger.condition

condition roboto.query.ConditionType | None #
Return type: Optional[roboto.query.ConditionType]

Trigger.create()

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)#View Source

Create a trigger in the caller’s org.

Parameters

name str

Trigger name, unique within the org.

What to dispatch on a match. At least one.

Platform event types to subscribe to (with once_per). At least one.

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.

The firing source itself, as an alternative to the events/once_per or schedule shorthands.

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

A cross-field validation rule fails (e.g. the condition references a root not exposed by every subscribed event).

The name is already taken in the org.

Trigger.delete()

delete()#View Source

Delete this trigger. Idempotent.

Return type

None

Trigger.disable()

disable()#View Source

Disable this trigger.

Return type

Trigger.dispatches()

dispatches(limit=100)#View Source

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]

Trigger.dry_run()

dry_run(event=None, dataset_id=None, file_id=None, invocation_id=None, event_id=None, event_type=None, scheduled_for=None)#View Source

Ask “would this trigger fire?” without dispatching anything.

Provide either a full event or exactly one entity reference, from which the server synthesizes an event (event_type optionally picks which kind). A schedule-fired trigger takes no reference: pass scheduled_for to 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.

Usage

trace = trigger.dry_run(dataset_id="ds_abc123")
print(trace.verdict)

Parameters

dataset_id Optional[str]
file_id Optional[str]
invocation_id Optional[str]
event_id Optional[str]
scheduled_for Optional[datetime.datetime]

Trigger.enable()

enable()#View Source

Enable this trigger.

Return type

Properties

Trigger.enabled

enabled bool #
Return type: bool

Trigger.engine

engine str #

Which trigger shape this trigger was created in: "v2", or "v1" for a trigger created through the older causes/for_each API.

Return type: str

Trigger.events

The subscribed event types, or None for a schedule-fired trigger.

Trigger.fires_on

What makes the trigger fire: an event subscription or a schedule.

Trigger.from_id()

classmethod from_id(trigger_id, roboto_client=None)#View Source

Load the trigger with the given id, whichever API created it.

Parameters

trigger_id str
roboto_client Optional[roboto.http.RobotoClient]

Return type

Trigger.from_name()

classmethod from_name(name, owner_org_id=None, roboto_client=None)#View Source

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

Trigger.list()

classmethod list(owner_org_id=None, roboto_client=None)#View Source

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]

Properties

Trigger.name

name str #
Return type: str

Trigger.once_per

What the trigger fires at most once per; always occurrence (one firing per minute) for a schedule.

Trigger.org_id

org_id str #
Return type: str

Trigger.platform_event_samples()

classmethod platform_event_samples(roboto_client=None)#View Source

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.path list a condition field or {{ }} placeholder may name. Use it to see what a template will resolve to before writing one.

Usage

samples = Trigger.platform_event_samples()
samples[PlatformEventType.FileUploaded].paths[:3]
# ['envelope.id', 'envelope.type', 'envelope.time']

Properties

Trigger.schedule

schedule str | None #

The cron expression (UTC) the trigger fires on, or None for an event-fired trigger.

Return type: Optional[str]

Trigger.set_enabled()

set_enabled(enabled)#View Source

Enable or disable this trigger.

Parameters

enabled bool

Return type

Trigger.to_dict()

to_dict()#View Source

Return this trigger’s record as a JSON-able dict.

Return type

dict[str, Any]

Properties

Trigger.trigger_id

trigger_id str #
Return type: str

Trigger.update()

update(*, fires_on=NotSet, events=NotSet, once_per=NotSet, schedule=NotSet, condition=NotSet, targets=NotSet, enabled=NotSet)#View Source

Apply a partial update to this trigger and refresh this instance.

Only provided fields change; condition=None clears the condition. The firing source is replaced whole: pass fires_on, or the events / once_per / schedule shorthands, which are merged over the current source before being sent. A trigger with engine == "v1" accepts only edits its older shape can express — a single invoke-action target, event types that map onto it, once_per of file or dataset — and rejects the rest with a message naming what it cannot store.

TriggerDispatchRecord

class roboto.domain.triggers.TriggerDispatchRecord(/, **data)#View Source

Bases: pydantic.BaseModel

Wire-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 the DispatchSlot; at most one dispatch ever occupies a slot, which is what makes redelivered events safe.

Parameters

data Any

Attributes

TriggerDispatchRecord.claimed_at

claimed_at datetime.datetime #

When the slot was (most recently) claimed.

TriggerDispatchRecord.dataset_id

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. None when the subject has no dataset, such as an invocation.

TriggerDispatchRecord.event_id

event_id str #

Id of the platform event occurrence that most recently claimed this slot.

TriggerDispatchRecord.event_type

Type of the platform event that matched.

TriggerDispatchRecord.finalized_at

finalized_at datetime.datetime | None = None #

When the dispatch reached a terminal status; None while claimed.

TriggerDispatchRecord.idempotency_token

idempotency_token str #

Dedup token derived from the matched event at the trigger’s once_per ({event.type}|{once_per}:{projection}).

TriggerDispatchRecord.org_id

org_id str #

Organization that owns the trigger.

TriggerDispatchRecord.result_ref

result_ref str | None = None #

What a dispatched target produced: an invocation id, an agent thread id, or a Slack message timestamp, per target_type.

Properties

TriggerDispatchRecord.slot

The slot this dispatch occupies.

Return type: DispatchSlot

Attributes

TriggerDispatchRecord.status

Where this dispatch is in its lifecycle.

TriggerDispatchRecord.status_detail

status_detail str | None = None #

Human-readable detail for status, e.g. the error a failed target raised.

TriggerDispatchRecord.subject

subject str #

The entity the matched platform event was about, as a roboto:// URI; the same value as the event’s own subject.

Properties

TriggerDispatchRecord.subject_uri

subject as a parsed RobotoUri.

Attributes

TriggerDispatchRecord.target_id

target_id str #

Which of the trigger’s targets this dispatch ran.

TriggerDispatchRecord.target_type

Kind of target dispatched.

TriggerDispatchRecord.trigger_id

trigger_id str #

Trigger this dispatch belongs to.

TriggerDispatchStatus

class roboto.domain.triggers.TriggerDispatchStatus#View Source

Bases: roboto.compat.StrEnum

Lifecycle state of one dispatch: one attempt to run one target for one matched event.

Attributes

TriggerDispatchStatus.Claimed

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.

TriggerDispatchStatus.Dispatched

Dispatched = 'dispatched' #

The target ran; TriggerDispatchRecord.result_ref points at what it produced.

TriggerDispatchStatus.Failed

Failed = 'failed' #

The target raised; a redelivered event may claim the slot again.

TriggerDispatchStatus.Unknown

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.

TriggerDryRunGate

class roboto.domain.triggers.TriggerDryRunGate(/, **data)#View Source

Bases: pydantic.BaseModel

One gate’s result in a dry-run trace.

condition_leaves is populated only on the condition gate, targets only on target_prefilter, and idempotency_token/dispatches only on already_fired.

Parameters

data Any

Attributes

TriggerDryRunGate.condition_leaves

condition_leaves list[ConditionLeafTrace] | None = None #

Per-leaf results with actual values (condition gate only).

TriggerDryRunGate.detail

detail str | None = None #

Plain-English explanation of the outcome.

TriggerDryRunGate.dispatches

dispatches list[DispatchSlotTrace] | None = None #

Per-target dispatch-slot state at the token (already_fired gate only).

TriggerDryRunGate.gate

Which gate this is.

TriggerDryRunGate.idempotency_token

idempotency_token str | None = None #

The dedup token the event projects onto (already_fired gate only).

TriggerDryRunGate.status

Whether the gate passed, failed, or was short-circuited.

TriggerDryRunGate.targets

targets list[TargetAcceptanceTrace] | None = None #

Per-target prefilter decisions (target_prefilter gate only).

TriggerDryRunGateName

class roboto.domain.triggers.TriggerDryRunGateName#View Source

Bases: roboto.compat.StrEnum

The gates the evaluator runs, in evaluation order.

Attributes

TriggerDryRunGateName.AlreadyFired

AlreadyFired = 'already_fired' #

Is a dispatch slot still claimable at the trigger’s once_per?

TriggerDryRunGateName.Condition

Condition = 'condition' #

Does the trigger’s condition hold for the event?

TriggerDryRunGateName.Enabled

Enabled = 'enabled' #

Is the trigger enabled?

TriggerDryRunGateName.Subscribed

Subscribed = 'subscribed' #

Is the trigger subscribed to the event’s type?

TriggerDryRunGateName.TargetPrefilter

TargetPrefilter = 'target_prefilter' #

Does at least one target accept the event (pathspec and precondition gates)?

TriggerDryRunGateStatus

class roboto.domain.triggers.TriggerDryRunGateStatus#View Source

Bases: roboto.compat.StrEnum

Outcome of one gate in a dry run.

Attributes

TriggerDryRunGateStatus.Failed

Failed = 'failed' #

TriggerDryRunGateStatus.NotEvaluated

NotEvaluated = 'not_evaluated' #

An earlier gate failed, so this one was short-circuited.

TriggerDryRunGateStatus.Passed

Passed = 'passed' #

TriggerDryRunRequest

class roboto.domain.triggers.TriggerDryRunRequest(/, **data)#View Source

Bases: pydantic.BaseModel

Request 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, event_id, or scheduled_for), from which the server synthesizes an event. With an entity reference, event_type optionally 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

Attributes

TriggerDryRunRequest.dataset_id

dataset_id str | None = None #

Synthesize an event about this dataset.

TriggerDryRunRequest.event

A platform event to evaluate as-is.

TriggerDryRunRequest.event_id

event_id str | None = None #

Synthesize a platform event about this event (the annotation on your data).

TriggerDryRunRequest.event_type

Which subscribed event type to synthesize for an entity reference.

TriggerDryRunRequest.file_id

file_id str | None = None #

Synthesize an event about this file.

TriggerDryRunRequest.invocation_id

invocation_id str | None = None #

Synthesize an event about this invocation.

TriggerDryRunRequest.scheduled_for

scheduled_for datetime.datetime | None = None #

For a schedule-fired trigger: 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.

TriggerDryRunResponse

class roboto.domain.triggers.TriggerDryRunResponse(/, **data)#View Source

Bases: pydantic.BaseModel

The 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

Attributes

TriggerDryRunResponse.event_type

Type of the (given or synthesized) event that was evaluated.

TriggerDryRunResponse.gates

gates list[TriggerDryRunGate] #

The gate-by-gate trace, in evaluation order.

TriggerDryRunResponse.trigger_id

trigger_id str #

The trigger that was dry-run.

TriggerDryRunResponse.verdict

verdict str #

One plain-English sentence summarizing the outcome.

TriggerDryRunResponse.would_fire

would_fire bool #

Whether the trigger would dispatch at least one target for this event.

TriggerRecord

class roboto.domain.triggers.TriggerRecord(/, **data)#View Source

Bases: pydantic.BaseModel

Wire-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_per legality, template placeholders — are enforced when the trigger is saved, by TriggerValidator.

Triggered work runs as the organization’s actions service user; a trigger cannot run its targets as anyone else.

Parameters

data Any

Attributes

TriggerRecord.condition

condition roboto.query.ConditionType | None = None #

Optional predicate over the firing’s namespace; the trigger fires only when it holds. Same Condition wire format the query system uses.

TriggerRecord.created

created datetime.datetime #

Timestamp when the trigger was created.

TriggerRecord.created_by

created_by str #

User ID who created the trigger.

TriggerRecord.enabled

enabled bool = True #

Whether the trigger is active.

TriggerRecord.engine

engine str = 'v1' #

Which engine evaluates this trigger: "v2" for the events/once_per/targets engine this module models (every trigger, once a deployment has cut over), "v1" for a trigger the older causes/for_each engine 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.

TriggerRecord.fires_on

What makes the trigger fire: an EventSubscription (which also carries once_per) or a Schedule.

TriggerRecord.managed_by

managed_by ManagedBy | None = None #

The owner of the trigger’s definition when it is not the org’s members, e.g. the ingestion rule the trigger ingests files for; None for a trigger a user created. Server-assigned and read-only; no request model carries it.

TriggerRecord.modified

modified datetime.datetime #

Timestamp when the trigger was last modified.

TriggerRecord.modified_by

modified_by str #

User ID who last modified the trigger.

TriggerRecord.name

name str #

Human-readable name. Unique within org_id.

TriggerRecord.org_id

org_id str #

Organization that owns the trigger and whose events it sees.

TriggerRecord.targets

What the trigger dispatches when it fires, in order. At least one; each target_id is unique within the trigger.

TriggerRecord.trigger_id

trigger_id str #

Unique identifier for the trigger.

TriggerSource

roboto.domain.triggers.TriggerSource#View Source

A trigger’s firing source, discriminated on type.

TriggerSourceType

class roboto.domain.triggers.TriggerSourceType#View Source

Bases: roboto.compat.StrEnum

Discriminator for TriggerSource.

Attributes

TriggerSourceType.Events

Events = 'events' #

The trigger fires when a subscribed platform event occurs.

TriggerSourceType.Schedule

Schedule = 'schedule' #

The trigger fires on a cron schedule.

TriggerTargetSpec

roboto.domain.triggers.TriggerTargetSpec#View Source

A trigger target spec, discriminated on type.

TriggerTargetType

class roboto.domain.triggers.TriggerTargetType#View Source

Bases: roboto.compat.StrEnum

The kind of thing a trigger does when it fires.

Attributes

TriggerTargetType.InvokeAction

InvokeAction = 'invoke_action' #

Invoke a containerized action.

TriggerTargetType.SendSlackMessage

SendSlackMessage = 'send_slack_message' #

Post a message to a Slack channel on the org’s allowlist.

TriggerTargetType.StartAgent

StartAgent = 'start_agent' #

Start an AI agent thread from a saved agent definition.

TriggerValidator

class roboto.domain.triggers.TriggerValidator(catalog=DEFAULT_PLATFORM_EVENT_CATALOG)#View Source

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_per must 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 reserved envelope./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.

TriggerValidator.validate()

validate(*, fires_on, condition, targets, managed_by=None)#View Source

Validate the cross-field rules for one trigger’s parts.

Parameters

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.

The trigger’s owner, if it is managed. An ingestion rule’s trigger accepts only the files the rule’s path patterns match, so its per-file targets need no required_inputs.

Raises

ValueError

The first rule that fails, with a message naming the offending field, root, or event.

Return type

None

TriggerValidator.validate_record()

validate_record(record)#View Source

Validate a full trigger record.

Raises

ValueError

Any rule in validate() fails.

Return type

None

UpdateTriggerRequest

class roboto.domain.triggers.UpdateTriggerRequest(/, **data)#View Source

Bases: pydantic.BaseModel

Request payload to update a trigger.

Only fields explicitly provided are changed; the NotSetType sentinel distinguishes “field omitted” from “field set to None”. The updated record must still satisfy every TriggerValidator rule.

Parameters

data Any

Attributes

UpdateTriggerRequest.condition

New condition; explicit None clears it.

UpdateTriggerRequest.enabled

New enabled status.

UpdateTriggerRequest.fires_on

New firing source. Replaces the whole source: an event subscription’s events and once_per change together, and a trigger may switch between events and a schedule.

UpdateTriggerRequest.model_config

model_config #

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

UpdateTriggerRequest.targets

New target list. A target whose target_id is referenced by existing dispatches must keep that id.

iter_query_templates()

roboto.domain.triggers.iter_query_templates(invocation_input)#View Source

Yield every RoboQL query in invocation_input, in document order.

Parameters

invocation_input collections.abc.Mapping[str, Any]

Return type

collections.abc.Iterator[str]

map_query_templates()

roboto.domain.triggers.map_query_templates(invocation_input, transform)#View Source

Return invocation_input with transform applied to every RoboQL query it holds.

Parameters

invocation_input collections.abc.Mapping[str, Any]

An InvocationInput in 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

dict[str, Any]

A copy, shallow below the selectors it rewrites.

platform_event_sample()

roboto.domain.triggers.platform_event_sample(event_type, catalog=DEFAULT_PLATFORM_EVENT_CATALOG)#View Source

Build the sample for one event type.

The event, changed and tag roots are built by the same EventNamespace that serves them when a trigger fires; the entity roots are exactly the ones catalog exposes for the type.

platform_event_samples()

roboto.domain.triggers.platform_event_samples(catalog=DEFAULT_PLATFORM_EVENT_CATALOG)#View Source

A sample for every event type in catalog, in catalog order.

sample_schedule_trigger()

roboto.domain.triggers.sample_schedule_trigger()#View Source

The schedule-fired trigger the schedule.fired sample is evaluated for, so the sample’s schedule root carries the cron a template may name.

sample_trigger()

roboto.domain.triggers.sample_trigger()#View Source

The trigger the sample is evaluated for; what {{trigger.*}} sees.

substitute_query_template()

roboto.domain.triggers.substitute_query_template(query, resolve)#View Source

Return query with each placeholder replaced by resolve’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

target_catalog_manifest()

roboto.domain.triggers.target_catalog_manifest()#View Source

The kinds of target a trigger can have, as the web UI’s target picker reads them.

target_catalog.json in this package is this function’s output, written by scripts/gen_trigger_manifests.py and 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]

template_paths()

roboto.domain.triggers.template_paths(record, prefix)#View Source

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.tags is addressable, dataset.tags.0 is not.

Parameters

record collections.abc.Mapping[str, Any]
prefix str

Return type

list[str]

Was this page helpful?