@task for application-owned queue work. A task is not model-visible; an Agent Tool decides when to defer it.
Define and call a task
From the agent root, create a compilable task starter:--project <agent-root> when running the command from elsewhere. The generated file is suitable when no other module imports the task; use the shared-library pattern below when tools also import it.
When a tool needs the task callable, define it once in lib/ and re-export it from tasks/:
tasks/<name>.py. The file must export exactly one same-named @task callable.
Control a job
The returnedTaskHandle supports await handle.status(), await handle.cancel(), and await handle.result(). A handle belongs to the active compiled runtime; there is no public API to reconstruct or list handles by ID.
Inside
@tool(durable=True), Harnest derives a replay-stable idempotency key when you omit one. Keep task effects idempotent because workers can retry.
Use await task.defer(...) without handle.result() for fire-and-forget work. Await a result only from an async @tool(durable=True) when the agent must resume after the Task finishes. An unfinished result requires a Harnest-owned checkpointer.
Runtime requirements
Configure Task and cron storage before serving queued work. That guide shows how to set up a database connection in a shared factory and provide its configuration through the environment. Every replica can run a worker against the same provider. Run these commands from your agent folder after configuring storage:
.defer() from an ordinary imported module without an active compiled runtime raises TaskUnavailableError; call the task body directly for isolated unit tests.
Start a fresh agent session
A task can invoke the compiled root agent without an HTTP call:tasks/review_report.py
key is optional. When supplied, Harnest derives the same opaque child session
and invocation identities on a task retry. User-deferred tasks inherit the
calling user and public metadata. Static schedules use Harnest’s automation
identity; dynamic schedules run as their creating user with fresh context and
empty grants. Calls still pass through storage, plugins, lifecycle, tools, and the
selected framework runtime.
When .defer() runs under an Agent Runtime Principal, Harnest stores only its permission names and reconstructs a fresh principal for each worker attempt. Agent calls made by the Task inherit that restriction unless trusted task code passes a narrower principal. A Task deferred without an active principal preserves compatibility behavior.
Durable external waits return a typed in_progress response. Human approvals
and client tools fail closed because their continuation is process-local after
the task returns.
See Durable execution for cross-replica resume behavior.
Test Task behavior
Call the decorated function directly to unit-test its business logic without a database. Exercise.defer(), retries, cancellation, and durable resume through a compiled smoke test with your chosen persistent provider so the real queue and checkpoint boundaries run together. Custom providers can use the shared conformance suite.