Skip to main content

Temporal-backed workflow runtime for Claude Code skills

Project description

sagaflow

CI PyPI Python 3.11+ License: MIT

Durable execution for long-running agent workflows, on top of Temporal.

You write a Python workflow that calls models, runs tools, and writes artifacts. sagaflow runs each step as a Temporal activity, so when the worker dies — or a 40-minute fan-out crashes halfway — the next launch resumes from the last completed step instead of starting over. Results land in ~/.sagaflow/INBOX.md whether or not you're still attached to the session that started them.

Quick start

pip install sagaflow
temporal server start-dev &
export ANTHROPIC_API_KEY=sk-ant-...

sagaflow launch hello-world --name alice --await
# → hello, alice

Kill the terminal mid-run and re-launch the same workflow ID: it picks up from where the worker died.

What you get

  • Resumes after crashes. Activity-level checkpointing via Temporal — workers, sessions, and laptops can all die without losing in-flight work.
  • Decoupled from the caller. Fire-and-forget submissions land in an append-only inbox; a session-start hook surfaces unread results next time you open Claude Code.
  • Provider-agnostic transport. Anthropic SDK by default; point ANTHROPIC_BASE_URL at Bedrock, a model gateway, or any compatible proxy.
  • Auto-managed worker. First sagaflow launch spawns a worker daemon; sagaflow doctor reports health.

Install

pip install sagaflow

Requirements:

  • Python 3.11+
  • Temporal CLI running locally: brew install temporal && temporal server start-dev
  • An Anthropic API key (or a compatible proxy via ANTHROPIC_BASE_URL)

Authoring a workflow

from sagaflow import workflow, generate_text, parallel, write_file

@workflow(name="code-review", phases=["Critique", "Synthesize"])
async def run(diff: str):
    findings = await parallel(
        generate_text("security-critic", variables={"diff": diff}),
        generate_text("perf-critic", variables={"diff": diff}),
    )
    report = await generate_text("synth", variables={"findings": str(findings)})
    await write_file("report.md", report)
    return report

Prompts live in prompts/<name>.prompt next to the workflow file. Each generate_text and write_file call is a Temporal activity with its own retry policy and replay log.

CLI

sagaflow launch <name> --arg key=value [--await]   # submit a workflow
sagaflow inbox                                     # list unread results
sagaflow dismiss <run-id>                          # mark as read
sagaflow doctor                                    # diagnose temporal/worker/hook

How it works

sagaflow launch
   │
   ▼
preflight (install hook, spawn worker if missing)
   │
   ▼
Temporal (localhost:7233) ── workflow ID ── worker daemon
                                              │
                                              ▼
                                         activities:
                                          • model calls
                                          • file I/O
                                          • inbox emit
                                              │
                                              ▼
                              ~/.sagaflow/INBOX.md  +  desktop notify
                                              │
                                              ▼
                                  next session: SessionStart
                                  hook surfaces unread runs

If the worker crashes mid-run, the next sagaflow launch (or the next worker poll) resumes from the last completed activity. Activities that already succeeded don't re-execute.

Development

git clone https://github.com/npow/sagaflow
cd sagaflow
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

ruff check sagaflow tests
mypy sagaflow
pytest

# Opt-in end-to-end tests (require live Temporal + real Anthropic access)
SAGAFLOW_E2E=1 pytest

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sagaflow-0.10.9.tar.gz (529.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sagaflow-0.10.9-py3-none-any.whl (252.8 kB view details)

Uploaded Python 3

File details

Details for the file sagaflow-0.10.9.tar.gz.

File metadata

  • Download URL: sagaflow-0.10.9.tar.gz
  • Upload date:
  • Size: 529.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for sagaflow-0.10.9.tar.gz
Algorithm Hash digest
SHA256 6b7dc75bbac56a74af52b8e4bf5155a9f70cde13dc852c7bc4fce26f06ac54b0
MD5 d2ad2b4ac0c56c2e60ef8bb1d1436b3a
BLAKE2b-256 dda2ff6222c5e224ec414d8456d62bda0c4e335df86c7b3ee36b96f8b39479a2

See more details on using hashes here.

Provenance

The following attestation bundles were made for sagaflow-0.10.9.tar.gz:

Publisher: publish.yml on npow/sagaflow

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sagaflow-0.10.9-py3-none-any.whl.

File metadata

  • Download URL: sagaflow-0.10.9-py3-none-any.whl
  • Upload date:
  • Size: 252.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for sagaflow-0.10.9-py3-none-any.whl
Algorithm Hash digest
SHA256 97a1fa78098147cbecbadd9a9095276d358d1f30357d74a94362dc2fe8370843
MD5 75ed1c2d6ddb6e3859a9f02dd6a6ebc1
BLAKE2b-256 73cc62f2f9d5b85784db8f2fbc6388ca988ed4f17363a9dcdc78a1ea66d83bd9

See more details on using hashes here.

Provenance

The following attestation bundles were made for sagaflow-0.10.9-py3-none-any.whl:

Publisher: publish.yml on npow/sagaflow

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page