Routines

Unattended agent turns need defined permissions and recorded results. A routine runs a scheduled prompt under its creator's identity and stores each result in its conversation.

A routine is an unattended task, such as a morning digest, weekly review, or one-time report. You declare it as a Routine resource in the declarative catalog. The resource contains a cron or one-time schedule and a prompt. At each scheduled time, the control plane runs that prompt in the routine's conversation under its owner's identity.

A schedule and a prompt

Ask the agent to create a routine. The control plane compiles your request into a spec and records its provenance. For example:

YAML
apiVersion: polychrome.dev/v1alpha1
kind: Routine
metadata:
  name: weekday-standup
spec:
  schedule:
    cron:
      expression: "0 9 * * 1-5"   # five-field cron, Sunday = 0
      timezone: America/New_York  # IANA zone; UTC when unset
  payload:
    prompt: "Summarize open pull requests and write a standup digest."
  provenance:                     # stamped at creation, immutable after
    creatorPersona: persona-abc123
    conversationId: conv-xyz

Each firing receives the prompt without previous conversation history:

  • The routine enables ephemeral history, so each firing excludes earlier firing transcripts from the model context.
  • The prompt must include the context it needs because the routine does not read the conversation that created it.

A once schedule (an RFC 3339 instant in place of the cron block) fires at most one time, then the routine records a terminal Completed condition.

kubectl get routines shows readiness, scope, and the last and next firing times. An invalid spec enters the Degraded phase with its reason in status.message. The scheduler does not dispatch an invalid routine.

Every firing runs as its owner

The persona that creates a routine owns it. Its provenance is immutable, and each firing uses that persona's permissions, linking requirements, and budgets. If the control plane cannot resolve the owner, it denies the firing and records the refusal in the event log.

Routines stop firing when their owner leaves the instance permanently, and they report an Orphaned condition. An admin can delete an orphaned routine or duplicate its definition. The duplicate runs under the admin's identity and permissions.

Managing routines by chat

Ask the agent to create, list, pause, resume, delete, test-fire, duplicate, or change a routine's scope. The control plane performs these changes outside the sandbox. Changes that add capability require your approval. The approval card displays the compiled spec, including its prompt and next firing times. Pausing takes effect immediately and requires no approval.

An admin belongs to the deployment's configured administrator set. An owner is the persona whose conversation created the routine.

ActionWhoApproval
Createadminsrequired
List and inspectadmins; owners for their own routinesread-only
Pauseadmins, ownersnot required
Resumeadmins, ownersrequired
Deleteadmins, ownersrequired
Test-fireownersrequired
Duplicateadmins, ownersrequired
Change scopeownersrequired

Only the owner can authorize a test firing or change the definition's visibility. An owner retains these permissions after losing administrator status. Each change appends a signed lifecycle event before updating the resource. This records a tamper-evident, replayable management history.

What a firing does

Each control-plane replica runs a scheduler. A time-limited claim in the state plane selects one replica for each occurrence. The routine UID and scheduled time identify that occurrence. The scheduler uses the same in-process turn service as edges, including its durable dispatch and recovery rules. It requires no separate cron service or network authentication for dispatch.

Each firing runs in a sandbox and records its reply in the routine's conversation. It can use tools allowed by its agent scope and routine grants. An unattended firing stops when a required tool lacks a grant. The scheduler does not deliver the reply to a channel or inbox. Read results through the forensics UI or query API. Owners can read their own firings; admins can read firings across the deployment.

The scheduler skips a tick more than five minutes late and records a MissedFire condition. It waits for the next scheduled firing instead of queuing skipped ticks. Creating, pausing, or resuming a routine does not run past ticks. The scheduler restores the last firing position from the event log after a restart.

Spec reference

FieldRequiredMeaning
scheduleyesExactly one of cron (a five-field expression plus an optional IANA timezone, UTC when unset) or once (an RFC 3339 at instant; fires at most once).
payload.promptyesThe non-empty prompt each firing runs as one user message.
provenanceyescreatorPersona identifies the owner and principal for each firing. conversationId identifies the originating conversation. The control plane sets both fields at creation; they are immutable.
scopenoprivate (default) or public. Controls whether other members can view and duplicate the definition. It does not change execution permissions or access to firing results.
suspendnoThe pause intent: who paused it, when, and optionally why. A suspended routine skips its ticks and never backfills them on resume.
descriptionnoA description of the routine for the catalog.

The full schema is available via kubectl explain routine.spec.