Skip to content

v0.2.3 (beta)

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 06 Oct 07:32
8091ea3

thunc 0.2.3 is the last 0.2 release. It makes native tool calls the way agents work wherever they run: on Codex now, as on Claude Code, and in durable runs on Claude Code, which pick up after a crash mid-call. Durable agents can take tools=, the Claude API agent path no longer loses runs to max_tokens or a stalled reply, and edit can change many places at once.

8 tool-heavy tasks, Claude Sonnet 5.5, 3 runs each Passed Seconds per task $ per task
thunc 0.2.2 agents, text protocol (Codex, durable runs, fallbacks) 20/24 47 0.084
thunc 0.2.3 agents, text protocol 24/24 27 0.082
thunc 0.2.3 agents on Claude Code, native calls 24/24 8 0.021
Claude Code itself, for reference 24/24 10 0.078

Through the Claude API, thunc's agents passed 8 of 8 on Sonnet 5.5 ($0.023 a task) and on Opus 5.5 ($0.049 a task). On Codex, native calls took 30 seconds a task, against 45 for the text protocol 0.2.2 used there and 27 for Codex itself (16 of 16 each).

pip install --upgrade thunc
import thunc

thunc.configure(backend="codex")  # agents now make native tool calls here too


def find_issue(title: str) -> int:  # a tool is your own code, with a docstring for the model
    """Find an open issue by title. Returns its number, or 0."""
    return tracker.find(title)


triage = thunc.Agent("triage", workdir=".", tools=[find_issue], effort="high")


@triage.task
def flaky_tests() -> list[str]:
    """Run the tests three times and list the ones that fail only sometimes."""
    ...
# On a Temporal worker: durable runs take the agent's own tools now, and name those that may run
# again after a crash.
registry.agent_task("triage", flaky_tests, version="1", workspace_id="repo", retry_safe_tools=["find_issue"])

Native tool calls on Codex (#55)

  • The agent's tools are an MCP server that Codex calls, through the same relay as Claude Code: thunc carries out each call with its own tools, permissions and run record. Codex's own tools and your ~/.codex config stay out, its sandbox stays read-only, and only thunc's server is approved to run without asking.
  • A turn that ends without finish, or fails, is continued with codex exec resume. The run's Codex session is deleted when the run ends.
  • Fallback: when Codex can't start them, a run uses the text protocol with a warning. protocol="native" raises instead, and protocol="text" keeps the old way.

Durable runs (#56, #57)

  • On Claude Code, native calls in segments. One activity keeps one claude -p process for many model replies, and checkpoints the run and Claude Code's session before each reply's calls. If the worker stops or the CLI dies, the retried activity restores the session and continues it with --resume. The call that was in flight, asked for again, gets its old journal entry: it's replayed, waits for resolve(), or runs. Never twice.
  • tools=. Each call of the agent's own functions is journaled like a command: recorded before it runs and after, replayed when completed, and waiting for resolve() if a worker stopped mid-call. retry_safe_tools= names the ones that may simply run again.

The Claude API agent path (#52)

  • Agent(effort=...) on every backend. Claude 4.6 and later on the API get "high" by default; Claude Opus 5.5's own default is "medium", which is low for agentic coding.
  • Replies are streamed with room for 64,000 tokens. A reply cut off at max_tokens gets an error result for its calls instead of ending the run, pause_turn carries on, and a reply that sends nothing for timeout seconds is stopped and asked again (one Opus reply in the benchmark sent nothing for an hour).
  • Old tool results are cleared on long runs (context editing), tools are strict where the model and schema allow, and connection errors, rate limits and server errors are retried as a step.

Steadier agents everywhere (#51, #52, #53)

  • The text protocol reads replies that aren't only the action: the first complete action amid prose, a fence, <invoke> markup or made-up results, with a note to the model to keep to JSON. On Claude Code, a text step stops as soon as its action has arrived.
  • finish in the same reply as other calls is refused (except beside remember): in the benchmark, a run returned a guess written before its own read came back.
  • The model is told when few steps are left, in its last three replies before max_steps.

Better tools (#50, #51, #49)

  • edit takes replace_all, and edits for several changes to one file in one call, all made or none.
  • edit no longer needs a prior read: it only changes text the agent quotes exactly. write still replaces only a file read with read.
  • Large system prompts work on Claude Code: the prompt goes in a file, not on the command line, where large follow= files could pass the operating system's limit.

Tested

  • Offline tests run on Python 3.10–3.14 on Ubuntu, and on Windows; Temporal integration tests on Python 3.10 and 3.14, including a Claude Code run whose CLI dies mid-run. Tests can't reach a real claude, codex or jev.
  • Live: the tool-use benchmark on Claude Code (Sonnet 5.5), the Claude API (Sonnet 5.5 and Opus 5.5) and Codex, with the results in live_tests/bench_tooluse_report.md; a durable run on real Claude Code with the CLI killed after its first tool result, which finished with each effect done once.

Behavior changes

  • Agents on codex make native tool calls by default, and fall back to the text protocol if they can't.
  • Durable runs on claude-code make native tool calls. Runs already in progress keep the text protocol.
  • Agents on the Claude API think at effort high on Claude 4.6 and later.
  • edit no longer needs a prior read; write still does.
  • finish in the same reply as other calls is refused, except beside remember.
  • Nothing is removed.

Known issues: on Codex, native calls count each tool call as a step, so a long task reaches max_steps sooner, and their tokens aren't reported. Durable runs on Codex use the text protocol. On a fix in a long file, native calls take about twice Claude Code's steps. The full list is in CONTRIBUTING.md, and every change is in CHANGELOG.md.

Full changelog: v0.2.2...v0.2.3