TaskSultan Docs tasksultan.com

Orchestrator

The Orchestrator

The local control plane that owns queues, schedules, credentials, environments, job records, the human approval step and the Robot handoff.

The Orchestrator is the control plane. It decides what runs, with what, when and where. It keeps the record of what happened. It never executes an automation. When a job is ready the Orchestrator spawns the Robot's own run-package command and reads the summary the Robot prints back.

#What it owns

  • The queue and its work items, in queues/ and transactions/.
  • Schedules, in schedules/, with the dispatch loop that fires them.
  • The credential vault in vault.json, with the key material that seals it.
  • The Robot registry in robots/, including capability and environment binding.
  • Job records in jobs/, with the evidence index each run writes.
  • Deployments and activations, in deployments/, the control plane that decides which package a slot version resolves to.
  • The Action Centre in actions/, the record of human decisions.
  • The mailbox ingest, which reads a mailbox at the seam.
  • State inspection and garbage collection.

#Where its state lives

Everything sits under one state root. The default is orchestrator/state inside the project. TS_ORCHESTRATOR_ROOT overrides it. orchestrator run <jobdef.json> --root <stateRoot> accepts it per invocation. Two processes must point at the same root to see the same work.

There is no database by default. State is JSON files and append-only journals, written through an atomic write that writes a temporary file and renames it into place. A write that cannot land throws instead of vanishing. The one exception is the queue: setting TS_QUEUE_PROVIDER=sqlite swaps the queue and transaction queue onto <root>/queue.db. An unset or empty value keeps the file provider. An unknown value is refused by name rather than falling back.

The state root holds jobs/, evidence/, queues/, transactions/, schedules/, robots/, deployments/, actions/, requests/, mailbox/, vault.json, principals.json, approvals.json, governance.ndjson and action-centre.ndjson.

#How it relates to the Robot

The Robot contract is frozen and the Orchestrator sits beside it, not inside it. A run travels through the same channel Studio uses: the Orchestrator spawns robot run-package <package-dir> --runId <id> --artifacts <evidenceRoot> under the project's own tsx loader, with parameters and credentials delivered as environment variables. Credentials arrive as TS_CRED_<NAME>; nothing else about the vault reaches the child.

A job moves queued → claimed → running → completed or failed. A failure carries a failureClass so the reason is machine-readable: deployment, resolution, capacity, execution or claim. The runId names the evidence directory. jobs show <id> prints the row with its lineage.

The Robot is deliberately ignorant of the Orchestrator. It has no registry, no queue and no vault of its own.

#The commands

npx tsx orchestrator/cli.ts run <jobdef.json>       # enqueue + dispatch one job
npx tsx orchestrator/cli.ts jobs list               # recorded jobs
npx tsx orchestrator/cli.ts jobs show <id>          # one job, with credential lineage
npx tsx orchestrator/cli.ts robot register <id> --capabilities web,excel
npx tsx orchestrator/cli.ts robot heartbeat <id>
npx tsx orchestrator/cli.ts robot list

#Things that catch people out

The manual orchestrator run path is the ungoverned one. A scheduled job or a label-pinned job resolves through an activation in deployments/. Those activations are managed through the Orchestrator server, not this CLI. A label schedule whose state root has no activation will refuse.

The Orchestrator is a local service, not a hosted control plane. There is no multi-tenant cloud and no shared broker. Two schedulers pointed at one root are serialised by the tick lock; two pointed at different roots will double-fire the same cron expression.