Skip to content

Pack Authoring

Pack authoring is how you turn your workflow into CaseGraph code.

For the first workflow, use the package-first bootstrap:

casegraph init intake_review --output .casegraph/intake_review_pack --json

Use the lower-level transactional scaffold when you need direct control:

uv run --all-groups --python 3.13 casegraph packs scaffold --kind transactional \
  --pack-id my_transactional \
  --output .casegraph/my_transactional_pack \
  --json

What The Generated Files Mean

File What you edit
engine.v1.yaml Engine id, version, prompts, and declared action ids.
architectures/*.yaml Which workers belong to the pack.
prompts/workers/.../task.j2 Prompt text for future model-assisted worker paths.
prompts/workers/.../tests.yaml Expected prompt fragments for author-check.
models.py Typed metadata and action input models.
workers.py Decorated worker functions that return WorkerOutput.
actions.py Preview, apply, verify, and compensate callbacks for your action.
capabilities.py build_transactional_capabilities(...) wiring.
registry.py Worker registry. Edit when adding workers.
__init__.py Public pack factory and demo helpers.
developer_api_demo.py Runnable example for your pack.

Worker Shape

Generated workers use ordinary typed Python functions marked with @worker(...) and named worker steps:

from casegraph import WorkerContext, WorkerOutput, worker


@worker(id="intake_reviewer", resolves="intake")
def review_record(context: WorkerContext) -> WorkerOutput:
    metadata = _demo_metadata(context)
    with context.step("review_record", input_summary=metadata) as step:
        review = _review_record(metadata)
        step.output_summary(review)
        step.source(...)
        step.tool_call(...)
        step.observation(...)
        step.claim(...)
    return WorkerOutput()

CaseGraph turns recorded steps and WorkerOutput into worker-run provenance. Use one step for each operation a future reader should understand, such as retrieval, comparison, classification, or claim synthesis.

worker_function(...) remains available when you need to construct worker adapters manually, but new generated packs use the decorator because it keeps registry code small.

Transactional Action Shape

Generated transactional packs use helper-backed capabilities:

from casegraph import TransactionalActionDefinition, build_transactional_capabilities
from casegraph import local_commit_receipt, local_preview_diff

You own the action input and callbacks in actions.py. CaseGraph handles the repetitive proposal, preview, policy, commit, verification, and replay records for one local/fake action.

Edit And Check Loop

For the first edit, change one statement in workers.py and one preview or receipt summary in actions.py. Keep capabilities.py for proposal wording, policy rule id, and action wiring.

After editing generated files:

uv run --all-groups --python 3.13 casegraph packs validate \
  --pack-root .casegraph/my_transactional_pack \
  --json
uv run --all-groups --python 3.13 casegraph packs author-check \
  --pack-root .casegraph/my_transactional_pack \
  --json

Then run the demo. CaseGraph uses Postgres to persist append-only case events and replayable graph projections, so run the CaseGraph database command before persisted execution:

docker compose up -d postgres
uv run --all-groups --python 3.13 casegraph db upgrade --json
uv run --all-groups --python 3.13 python .casegraph/my_transactional_pack/developer_api_demo.py

Expected output:

worker=intake_reviewer
proposal_action=mark_intake_ready
policy_status=auto
commit_status=committed
replay_status=in_sync
inspect_command=casegraph cases inspect <case-id> --json

Inspect the persisted case after the demo:

casegraph cases inspect <case-id> --json

Use that report to confirm the edited worker evidence, proposed action, policy, commit receipt, and replay status before opening lower-level graph or event views.

If author-check fails after a worker edit, start with the file named in the issue. The most common fix is to keep the generated source, tool call, observation, and claim together, and to keep step.observation(subject=context.selected_item.topic, ...) unless you changed the gap topic too.

Larger Examples

  • examples/minimal_transactional_pack is the checked-in version of the generated transactional shape.
  • examples/minimal_readonly_pack shows a worker-only pack.
  • examples/pydantic_ai_adapter_pack shows how to cover a Pydantic-AI agent run from a worker without making Pydantic-AI a required dependency.
  • examples/support_escalation is a larger reference/demo pack.

Optional framework packs should declare their own extra install path, such as uv add "casegraph[pydantic-ai]", instead of making every CaseGraph project install every framework adapter.