thunc()
Reference

API reference

Every public function, option, environment variable and error in thunc 0.2, on one page. The guide pages explain each in context.

Functions

NameWhat it does
@thunc.functionTurns 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.callOne prompt. Inputs are sent separately from the instructions. name= groups its cached answers.
thunc.acallthunc.call, to await.
thunc.amapthunc.map, to await: up to workers calls at once, in input order. Takes async def and plain functions.
thunc.register_backendAdds 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.testingA fake model for your tests (fake_model, act, finish, isolated), and the thunc_model and thunc_isolated pytest fixtures.
thunc.mapRuns calls in parallel, keeping the input order.
thunc.configureProcess-wide settings.
thunc.clear_cacheDeletes saved answers: all of them, one function's, or those older than an age. Returns how many.
thunc.cache_infoWhat's in the cache: a list of thunc.CacheGroup, one per function, with its entries, size on disk and newest answer.
thunc.AgentAn agent: a name, a working directory, permissions and tasks.
@agent.task, @thunc.agentDeclare a task on an agent, or an agent with a single task.
agent.callA task built in code, like thunc.call.
agent.runRuns a task and returns a thunc.Run with what happened.
thunc.promptsSystem prompt presets for agents: CODING, CODE_REVIEW, ANALYSIS.
thunc.temporalOptional 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 anthropic or openai. An api_key with no backend means anthropic. Never sent to Jev.
model
The default model. anthropic defaults to claude-opus-5-5, openai to gpt-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=True answers 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

VariableMeans
THUNC_BACKENDThe backend, when neither the call nor configure sets one
ANTHROPIC_API_KEYClaude API key; selects anthropic when no backend is set
OPENAI_API_KEYOpenAI API key; selects openai when no backend is set and there's no Anthropic key
OPENAI_BASE_URLPoints the openai backend at another server, such as a local model
JEV_API_KEYJev key, in place of jev login
THUNC_TRACETrace file, like configure(trace=...)
THUNC_CACHE_DIRCache folder, like configure(cache_dir=...); also read by the thunc command
THUNC_AGENTS_DIRAgents folder, like configure(agents_dir=...)
THUNC_RECORDINGSRecordings folder, like configure(recordings=...): replay recorded answers
THUNC_RECORD1 asks the model and saves every answer to the recordings folder; missing saves only the answers it lacks
THUNC_WRITE0 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 ThuncError from an agent run that hit max_steps, never gave a valid value, or lost its backend. .run is the record up to that point.
thunc.TransientError
A ThuncError that 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.call and @thunc.function don'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. 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.

EventFields
startformat, task, instructions, inputs, returns, memory_characters, followed (path to hash), protocol (native, mcp, text or replay), and settings_changed_from when agent.json changed
fallbackprotocol, reason: native calls couldn't start, so the run went on the text protocol
retryattempt, error: a model reply that failed for a reason worth asking again
stepn and result; with tool, args and denied (only when true) for a tool call, or reply for a reply with no usable call
finishn, value, files_changed
errorerror, 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.

EventFields
call.startid, function, backend, model, inputs
call.attemptid, n, seconds, ok, reply, and problem when the reply was rejected
call.endid, ok, cached, replayed, attempts, seconds, value, error
agent.startid, agent, task, returns, session (the run's record), replayed, inputs
agent.replyid, n, seconds waiting on the model
agent.toolid, n, tool, target: a tool call starting
agent.stepid, n, tool, target, result, seconds, denied
agent.endid, 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.

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:

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 deleting

Also 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

Edit this page on GitHub