absurd
Absurd
Use this skill when the project uses Absurd, the Postgres-native durable workflow engine, or when the user mentions absurdctl, queues, durable tasks, runs, retries, sleeping tasks, or events.
Tiny mental model
- A queue is a namespace of Absurd tables (
t_,r_,c_,e_,w_). - A task is the durable workflow instance.
- A run is one execution attempt of a task.
- A step is a checkpoint. Completed step results are stored as JSON.
- Sleeping tasks are usually waiting for time or an event.
- Events wake waiting tasks. Event payloads are cached; first emit wins.
Important distinction:
task_id= the whole workflow across all attemptsrun_id= one specific execution attempt
First: make sure absurdctl works
If absurdctl is not on PATH, check whether you are inside a repo checkout and, if so, use:
export PATH="$PWD:$PATH"
Absurd connection precedence is:
--database > ABSURD_DATABASE_URL > PGDATABASE > postgresql://localhost/absurd
For non-URI connections, PGHOST, PGPORT, PGUSER, and PGPASSWORD are also honored.
Default debugging workflow
Prefer absurdctl state inspection before source inspection. Usually you do not need to read application code first.
If the user explicitly asks you to use absurdctl to inspect or fix a workflow, do that first instead of starting with rg / source browsing.
When the user wants to debug a task, start with these commands in order:
1) Discover queues
absurdctl list-queues
2) Inspect recent activity in the likely queue
absurdctl list-tasks --queue=default --limit=20
Notes:
list-tasksdefaults to 50 rows if--limitis omitted.- Useful statuses:
pending,running,sleeping,completed,failed,cancelled.
3) Focus on failures or sleepers
absurdctl list-tasks --queue=default --status=failed --limit=20
absurdctl list-tasks --queue=default --status=sleeping --limit=20
4) Inspect one workflow or one attempt in detail
absurdctl dump-task --task-id=<task-id>
absurdctl dump-task --run-id=<run-id>
dump-task is the most important inspection command. It shows things like:
- task name, params, and headers
- retry settings and attempts
- checkpointed step state
- waits / events / sleep state
- final result or failure
How to reason about common states
If a task is failed
dump-task --task-id=<task-id>- Read the failure and the last successful checkpoints.
- If needed, inspect the most recent attempt with
--run-id. - Search the code for the task implementation by task name.
- Only then decide whether to retry.
If a task is sleeping
dump-task --task-id=<task-id>- Look for the wait reason:
- sleeping until a timestamp
- waiting for an event name
- If it is waiting for an event and the user wants it resumed, emit that event.
If a task is running
dump-task --task-id=<task-id>- Look at existing checkpoints to see how far it got.
- If the user suspects a stuck worker, inspect the worker process / application logs too.
About workers
Do not assume you need to start or modify a worker.
- If a spawned task moves from
pendingtosleeping,running, orcompleted, a worker is already active. - If tasks remain
pending, then investigate whether a worker for that queue is actually running. - Only inspect Python / TypeScript runtime details when the task state suggests a worker problem or the user asks for code changes.
If you need the implementation
After you know the task name, search the codebase for its registration.
TypeScript / JavaScript:
rg -n "registerTask\(|name:\s*['\"]<task-name>['\"]" .
Python:
rg -n "register_task\(|@.*register_task|['\"]<task-name>['\"]" .
If the task is waiting for an event, also search for the event name.
Common actions
Spawn work
Use -P key=value for strings and -P key:=json for typed JSON values.
absurdctl spawn-task my-task -q default -P foo=bar
absurdctl spawn-task my-task -q default -P count:=42 -P enabled:=true
absurdctl spawn-task my-task -q default -P user.name=Alice -P user.age:=30
Use --params when the user already has a JSON object:
absurdctl spawn-task my-task -q default --params '{"foo":"bar","count":42}'
Retry failed work
absurdctl retry-task <task-id>
absurdctl retry-task <task-id> --max-attempts 5
absurdctl retry-task -q default <task-id> --spawn-new
Guidance:
- plain
retry-taskretries the existing task --spawn-newcreates a brand-new task with the original inputs- prefer understanding the failure before retrying
Cancel work
absurdctl cancel-task <task-id>
absurdctl cancel-task -q default <task-id>
Wake waiting tasks by emitting an event
absurdctl emit-event order.completed -q default -P orderId=123
absurdctl emit-event approval.granted:42 -q default -P approved:=true
If the event payload should be structured JSON:
absurdctl emit-event shipment.packed:42 -q default --payload '{"trackingNumber":"XYZ"}'
Schema setup / migrations
Use these on a blank or controlled database, or when the user explicitly asks:
absurdctl init
absurdctl schema-version
absurdctl migrate
absurdctl create-queue default
Safe operating rules
Be careful with state-changing commands. Unless the user clearly wants them, avoid running these blindly on a shared or production database:
initmigratecreate-queuedrop-queuecleanupcancel-taskretry-taskemit-eventspawn-task
If the environment is ambiguous, ask which database / queue is safe to operate on.
Good copy-paste playbooks
Debug the latest failures in default
absurdctl list-queues
absurdctl list-tasks --queue=default --status=failed --limit=20
absurdctl dump-task --task-id=<task-id>
Find sleepers and wake one
absurdctl list-tasks --queue=default --status=sleeping --limit=20
absurdctl dump-task --task-id=<task-id>
absurdctl emit-event <event-name> -q default -P key=value
Reproduce by spawning a task, then inspect it
absurdctl spawn-task my-task -q default -P foo=bar
absurdctl list-tasks --queue=default --task-name=my-task --limit=5
absurdctl dump-task --task-id=<task-id>
Fast path when the user says “spawn a task and debug it”:
absurdctl spawn-task my-task -q default -P foo=bar
absurdctl list-tasks --queue=default --task-name=my-task --limit=5
absurdctl dump-task --task-id=<task-id>
# then either:
absurdctl emit-event <event-name> -q default -P key=value
# or:
absurdctl retry-task <task-id>
Extra reference
- Use
absurdctl <command> --helpfor full options. dump-task --task-idis usually the best starting point once you know the task.- Checkpointed step results are durable JSON state; code outside steps may execute multiple times across retries.