API reference
Every public function, option, environment variable and error in thunc 0.7, on one page. The guide pages explain each in context.
Functions
| Name | What it does |
|---|---|
@thunc.function | Turns a signature and docstring into an AI-backed function. Options: instructions=, system=, ensure=, retries=2, backend=, model=, cache=False, write=False (experimental, thunc write: the function writes its own body). The body must be empty (...); real code raises TypeError. async def works. |
thunc.call | One prompt. Inputs are sent separately from the instructions. name= groups its cached answers. |
thunc.acall | thunc.call, to await. |
thunc.amap | thunc.map, to await: up to workers calls at once, in input order. Takes async def and plain functions. |
thunc.register_backend | Adds your own backend: a function from the prompt to the answer's text, or with typed=True a typed one. thunc.unregister_backend removes it. |
thunc.testing | A fake model for your tests (fake_model, act, finish, isolated), and the thunc_model and thunc_isolated pytest fixtures. |
thunc.map | Runs calls in parallel, keeping the input order. |
thunc.configure | Process-wide settings. |
thunc.clear_cache | Deletes saved answers: all of them, one function's, or those older than an age. Returns how many. |
thunc.cache_info | What's in the cache: a list of thunc.CacheGroup, one per function, with its entries, size on disk and newest answer. |
thunc.Agent | An agent: a name, a working directory, permissions and tasks. |
@agent.task, @thunc.agent | Declare a task on an agent, or an agent with a single task. |
agent.call | A task built in code, like thunc.call. |
agent.run | Runs a task and returns a thunc.Run with what happened. |
thunc.prompts | System prompt presets for agents: CODING, CODE_REVIEW, ANALYSIS. |
thunc.temporal | Optional durable runtime: Registry, Worker, Runtime. Needs thunc[temporal]. |
Signatures
@thunc.function(*, instructions=None, retries=2, ensure=None, backend=None, model=None,
system=None, cache=False, write=False)
thunc.call(instructions, inputs=None, *, returns=str, ensure=None, retries=2, backend=None,
model=None, system=None, cache=False, name=None)
thunc.map(func, items, *, workers=8)
await thunc.acall(...) # the arguments of thunc.call
await thunc.amap(func, items, *, workers=8)
thunc.register_backend(name, backend, *, typed=False, default_model=None, replace=False)
thunc.testing.fake_model(replies=None) # a context manager giving a FakeModel
thunc.clear_cache(function=None, *, older_than=None) # function or name; timedelta or seconds
thunc.Agent(name, *, workdir, system=None, permissions=(), env=None, command_timeout=120,
follow=False, protocol=None, tools=(), timeout=None, max_steps=40,
retries=2, backend=None, model=None, effort=None)thunc.configure
Sets defaults for every call. Arguments left out keep their current value.
- backend
"anthropic","openai","claude-code","codex"or"jev". See choosing a backend.- api_key
- The API key for
anthropicoropenai. Anapi_keywith no backend meansanthropic. Never sent to Jev. - model
- The default model.
anthropicdefaults toclaude-opus-5-5,openaitogpt-5.5. - timeout
- The time limit for each backend request, in seconds. Default 300.
- trace
- Path of a JSONL file that records every call.
- cache_dir
- Where
cache=Trueanswers go. Default.thunc_cache. - system
- A system prompt for every call in place of thunc's default. A per-call
system=wins. - agents_dir
- Where agents keep memory and run records. Default
.thunc_agents. - recordings
- A folder of recorded answers. Every call and agent run is answered from it and no model is asked; one that wasn't recorded raises
ThuncError. See record and replay.
Environment variables
| Variable | Means |
|---|---|
THUNC_BACKEND | The backend, when neither the call nor configure sets one |
ANTHROPIC_API_KEY | Claude API key; selects anthropic when no backend is set |
OPENAI_API_KEY | OpenAI API key; selects openai when no backend is set and there's no Anthropic key |
OPENAI_BASE_URL | Points the openai backend at another server, such as a local model |
JEV_API_KEY | Jev key, in place of jev login |
THUNC_TRACE | Trace file, like configure(trace=...) |
THUNC_CACHE_DIR | Cache folder, like configure(cache_dir=...); also read by the thunc command |
THUNC_AGENTS_DIR | Agents folder, like configure(agents_dir=...) |
THUNC_RECORDINGS | Recordings folder, like configure(recordings=...): replay recorded answers |
THUNC_RECORD | 1 asks the model and saves every answer to the recordings folder; missing saves only the answers it lacks |
THUNC_WRITE | 0 stops thunc write from writing, as in production; so does CI |
Errors
- thunc.ThuncError
- No valid answer arrived after the retries, the backend failed, or nothing is configured. Also raised when a function is declared with an unsupported return type.
- thunc.AgentError
- A
ThuncErrorfrom an agent run that hitmax_steps, never gave a valid value, or lost its backend..runis the record up to that point. - thunc.TransientError
- A
ThuncErrorthat asking again may fix: a timeout, a lost connection, a rate limit, a server error, or a CLI call that ended in an error. An agent run retries the step twice before failing;thunc.calland@thunc.functiondon't retry it. - TypeError
- Raised when a function is declared with code in its body, or with no docstring and no
instructions=.
Formats other programs read
Three files are meant to be read by other programs: an agent run's record, the THUNC_EVENTS stream that thunc watch reads, and a durable task's fingerprint. Recordings, at the end, are read by later releases of thunc itself. Each has a format number. Within one number, events and fields are only added, never removed or given another meaning, so a reader should ignore what it doesn't know. A change that an old reader would misread gets a new number, and the changelog says so.
An agent run's record
One JSON line per event in .thunc_agents/<agent>/sessions/, each with time and event. The first line, start, has "format": 1.
| Event | Fields |
|---|---|
start | format, task, instructions, inputs, returns, memory_characters, followed (path to hash), protocol (native, mcp, text or replay), and settings_changed_from when agent.json changed |
fallback | protocol, reason: native calls couldn't start, so the run went on the text protocol |
retry | attempt, error: a model reply that failed for a reason worth asking again |
step | n and result; with tool, args and denied (only when true) for a tool call, or reply for a reply with no usable call |
finish | n, value, files_changed |
error | error, files_changed: the run failed |
The THUNC_EVENTS stream
One JSON line per event, each with "v": 1, event, t (Unix time) and pid. Inputs, replies and values are short previews unless THUNC_EVENTS_CAPTURE=1.
| Event | Fields |
|---|---|
call.start | id, function, backend, model, inputs |
call.attempt | id, n, seconds, ok, reply, and problem when the reply was rejected |
call.end | id, ok, cached, replayed, attempts, seconds, value, error |
agent.start | id, agent, task, returns, session (the run's record), replayed, inputs |
agent.reply | id, n, seconds waiting on the model |
agent.tool | id, n, tool, target: a tool call starting |
agent.step | id, n, tool, target, result, seconds, denied |
agent.end | id, ok, steps, seconds, files_changed, value, error |
Durable task fingerprints
A durable task's fingerprint is a hash of what it was registered with: its instructions, the JSON Schema of its return type, the backend, the model, the API endpoint, the agent's settings (permissions aside) and its tools. A worker refuses to continue a run whose fingerprint differs, so a changed task needs a new version.
- Upgrading thunc doesn't change a fingerprint. A task registered the same way gets the same fingerprint on every 0.x release from 0.6 on, and the same holds through 1.x. A new option only joins the fingerprint when it's set, so tasks that don't use it keep theirs.
- If a release must change fingerprints, for example to fix one that missed something a run depends on, the changelog says so under Behavior changes, a release ahead where possible: let runs on the old fingerprints finish before upgrading the workers.
tests/temporal/test_fingerprints.pypins the fingerprints of a set of task definitions, so a change to one fails the tests.
Recordings
A recording is named by a hash of what your code says about a call or agent run, not of the text thunc sends the model, so a release that rewords thunc's prompts leaves your recordings where they are.
- Upgrading thunc keeps your recordings. A call or run written the same way gets the same name on every release from 0.7 on, through 1.x. A built-in tool added in a later release doesn't join an agent run's name.
- Recordings made with 0.4 to 0.6 are named by the text thunc sent then. They're still found, and recording an answer again with
THUNC_RECORD=1saves it under its new name and removes the old file. tests/test_recordings.pypins the names of a set of calls and runs, in both formats, so a change to one fails the tests.
What's stable
From 0.6, the agent API is frozen: thunc.Agent and its methods, @thunc.agent, thunc.Run, thunc.AgentError, and the run record. Together with the rest of thunc.__all__ and thunc.testing, it's listed signature by signature in tests/api.txt, and a test fails on any change to it. Additions are made freely; a removal or a change goes through a deprecation (below). Two things stay outside that promise:
- thunc write (
write=Trueand thethunc writecommand) stays experimental through 1.0: it may change, or be removed, without a deprecation period. - The thunc watch dashboard's screens and keys may change as feedback comes in; the events it reads are a versioned format.
thunc.temporal, the optional durable runtime, may change in a later release; its task fingerprints keep their own promise.
Deprecations
Part of the API that's going away keeps working for at least two minor releases, and warns with thunc.ThuncDeprecationWarning where you use it, naming the release that removes it and what to use instead. The warning is shown by default, once per place in your code; turn it off with warnings.filterwarnings("ignore", category=thunc.ThuncDeprecationWarning), or make it an error in your tests with -W error::thunc.ThuncDeprecationWarning. The changelog lists deprecations and removals in each release. Experimental features (thunc write) can change without one.
Command line
thunc run --profile app.py --limit 20 # run a script, then print where the time went
thunc run --profile -m myapp.triage # a module, as with python -m
thunc write app.py::minutes --dry-run # experimental: write a write=True function now (--dry-run: show the diff)
thunc cache list # saved answers per function
thunc cache clear # everything
thunc cache clear --function urgency # one function (repeat for several)
thunc cache clear --older-than 30d --dry-run # what would go, without deletingAlso python -m thunc, and thunc --version. thunc run runs the program as python would and passes its exit code through; --profile adds the performance report. thunc write (experimental) writes a write=True function ahead of its first call. The cache commands take --cache-dir, or read THUNC_CACHE_DIR; point --cache-dir at a recordings folder to list or clear its recordings.
Limitations
- Docstrings disappear under
python -OO. Useinstructions=there.