---
name: trigora
description: Add Trigora durable execution to a TypeScript, Python or Rust codebase. Use when making a long-running agent, workflow or job survive crashes, waits and deploys with Trigora; when writing a Trigora Program with effect, waitForEvent / wait_for_event, sleep or invoke; or when a Trigora compile error, recovery question or deploy step comes up.
---

# Trigora

Trigora is a durable execution runtime. A Program is ordinary TypeScript, Python or Rust compiled to bytecode. At each durable operation the host commits the Program's control position and the values it needs to continue. After a crash it restores that continuation instead of replaying earlier steps.

Source of truth: https://trigora.dev/docs/agent-quickstart/ and https://trigora.dev/llms-full.txt. When this file and the docs disagree, the docs win.

## Workflow

1. Read https://trigora.dev/llms.txt, then https://trigora.dev/docs/quickstart/ and https://trigora.dev/docs/authoring/supported-semantics/.
2. Pick the SDK that matches the project: TypeScript (`@trigora/sdk`, Node.js 22 or 24), Python or Rust. Python-only and Rust-only projects do not require Node.js.
3. Run `trigora init` for the chosen language. Start with one small Program for an existing long-running task.
4. Run `trigora verify` (below) and prove recovery locally before suggesting any deploy.
5. Ask the user before choosing Trigora Cloud or Trigora Pulse, before creating a `TRIGORA_TOKEN` and before running `trigora deploy`. Pulse v1.0.0 is published as `ghcr.io/trigora-dev/pulse:1.0.0`. It runs the Node adapter on Node.js 22 or 24. `trigora pulse start` starts that host; `trigora start` does not. There is no Python or Rust Pulse adapter.

## Rules that decide whether a Program compiles and recovers

- Durable operations are explicit imports: `effect`, `waitForEvent` / `wait_for_event`, `sleep`, `invoke`, and in Rust also `join` and `race`. A local function with the same name is not a durable operation.
- Durable operations stay in the program entry. A helper or closure frame cannot perform one. A closure value may live across a wait.
- Effect keys and event names are non-empty string literals. `effect(fn)` without a name is rejected. Keep names stable across retries of the same logical step.
- Put every model, tool and network call inside `effect("<name>", fn)`.
- `Promise.all`, `Promise.race`, `gather`, `race`, and Rust `join` / `race` compile only in the forms on https://trigora.dev/docs/authoring/structured-concurrency/. `Promise.any`, `Promise.allSettled`, `.then`, stored promises and `asyncio.gather` do not.
- Constructs outside the language profile fail at compile time. Check https://trigora.dev/docs/authoring/unsupported/ before restructuring code.

## Side effects

- A committed effect outcome is reused on recovery and its function does not run again.
- If the process dies after the function started and before the outcome committed, the function can run again. Trigora does not provide exactly-once delivery to external systems.
- Pass an idempotency key to any API that charges, sends or writes, and keep it in a system that survives retries.
- `trigora cancel` does not undo a committed effect.

## Verify recovery with trigora verify

```bash
trigora verify <program> --faults all --effects fixtures.json
```

- Records a healthy baseline, crashes after committed boundaries, resumes, and compares. Runs in-process on temporary SQLite; it does not start `trigora dev` or contact Cloud or Pulse.
- Exits non-zero if a recovery fails, the result differs, or an effect runs twice or goes missing. Use it as a CI gate, and fix failures before moving on.
- `--faults sample` (default) checks up to 8 boundaries; `--faults all` checks every one.
- Programs with effects need `--effects`. Prefer a fixtures file (JSON object of effect key to result). `--effects live` calls real handlers during the baseline, so ask first for calls that charge, send or write.
- `--events` supplies event payloads (missing ones receive `"ok"`); sleeps are fast-forwarded; `--input` matches `trigora start`; `--out verify.json` writes a report.
- `trigora bench <program>` profiles one healthy run. Docs: https://trigora.dev/docs/testing/bench-and-verify/

## Prove recovery under trigora dev

```bash
trigora init
trigora dev                                   # leave running
trigora start <program>                       # in another shell
# kill trigora dev while the execution waits, start it again
trigora send <execution-id> <event>
trigora executions inspect <execution-id>
```

Confirm that nothing before the wait ran again. The wait restores from local SQLite.

## Pulse

Pulse v1.0.0 is published: https://github.com/trigora-dev/trigora/releases/tag/pulse-v1.0.0 and `ghcr.io/trigora-dev/pulse:1.0.0` (Linux AMD64 and ARM64). You run the process. Trigora stores the checkpoint.

- The adapter is Node.js 22 or 24. Python and Rust authoring elsewhere does not mean a Pulse adapter exists.
- `trigora pulse start` compiles the project and starts the host and the Node adapter. It requires `TRIGORA_TOKEN` on the host unless `--ephemeral`. It prints `ready` and does not create an execution.
- `trigora pulse connect --dir <socket dir>` registers with a host that is already running. `--prepare` writes the handler manifest and exits.
- `trigora start` is `trigora dev` or Cloud with `--remote`. It is not the Pulse start path.
- A waiting execution stays on its artifact hash. Keep that artifact available. The checkpoint cap is 16 MiB. There is no continuation migration.

## Secrets

- `TRIGORA_TOKEN` authenticates Trigora Cloud. There is no `trigora login`. Keep it in the environment or a `.env` file.
- Never print, log or commit tokens or secrets. Do not put credentials in Program constants, inputs or event payloads; they are stored with the Execution.
- `trigora dev` reads the local process environment, not Cloud secrets.

## Limits to state honestly

- Recovery cost scales with live state. It is not a general latency guarantee and does not fix failures in the systems effects call.
- Waiting Executions stay on the artifact they started with; a new deploy does not migrate them.
