StackMap
Subscribe
Explore / spec-ptc
alexzhang13

spec-ptc

Speculative programmatic tool calling: while the model is still streaming a code block, the harness launches the tool and sub-LLM calls it is about to make, so blocking calls overlap generation.

178 13 Python MITupdated 4 days ago
View on GitHubDispute this mapping →
Curator's take

A narrow, sharp optimization for code-as-tool-calling harnesses. In programmatic tool calling — RLM, CodeAct, Claude's PTC — every tool is a function inside one generated REPL block, and for recursive harnesses the sub-LLM calls inside that block dominate wall-clock. sPTC watches the token stream, and as soon as a statement closes it speculatively runs the call in a shadow fork, so by the time `exec` fires the results are already claimed. Decorate a tool `speculatable=True, pure=True` to opt in; anything with side effects is never speculated, which is the right default. Adopt it if sub-LLM or sub-agent latency inside a REPL is your bottleneck — one line patches RLM, and a stdlib daemon plus ~60-line client covers arbitrary harnesses (Claude Code PreToolUse, OpenCode, Pi-mono wrappers included). Ignore it if your tools are cheap or impure: you pay speculative calls on every miss, and there is no benefit to hide.

Mapped by ShipWithAI editors · links verified
README.md

Speculative Programmatic Tool Calling

Speculative programmatic tool-calling (sPTC) is a technique for harnesses that use tools like sub-agents / sub-calls in code. While the LLM is streaming tokens to generate a REPL call, sPTC speculates and queues up tool calls in the partially-generated code that act as Futures when the actual code is executed.

Learn more in the blogpost here.

sPTC vs serial comparison

Many harness designs like Recursive Language Models (RLMs) and CodeAct rely on programmatic tool-calling (PTC), where all tools are embedded as functions inside a single code REPL tool that is generated per turn. For RLMs in particular, sub-LLM and sub-RLM calls are expensive, often blocking tools in code that take up a majority of the runtime. sPTC is the general technique of speculating tool and sub-LLM calls that will happen as the root LLM is generating the codeblock, allowing the RLM to batch and asynchronously compute these expensive calls while the full codeblock is still being generated to overlap these calls with the logic of the code REPL.

baseline   tokens──────────────────▶ exec: call₁──▶call₂──▶…──▶callₙ──▶ answer
spec-ptc   tokens──────────────────▶ exec: claim·claim·claim ──▶ answer
                 ╲ call₁ ▶▶▶ done ╱
                  ╲ call₂ ▶▶▶ done╱     (calls run inside generation time)

This repository is a simple library and demo for this technique.

Getting Started

You can either clone this repository (uses uv), or install with:

pip install spec-ptc

The Speculator object is used to track and store tools to be speculated, as well as the shadow REPL that is used to speculate. You can add tools with the spec.tool decorator and control whether you want them to be speculated or not.

The simplest example is to install tool hooks into the REPL you already have, feed tokens as they stream and feed them to the speculator, then exec as usual when finished:

from spec_ptc import Speculator

spec = Speculator()


# tools can also be async
@spec.tool(speculatable=True, pure=True)  # add as tool to be speculated
def llm_query(prompt: str) -> str:
    return sub_lm.complete(prompt)


@spec.tool()  # side effects: never speculated
def send_report(text: str) -> str:
    return mail.send(text)


ns.update(spec.hooks())  # same names, claim-or-run

code = ""
with spec.turn(repl_locals=ns) as t:  # snapshot → discarded shadow fork
    for delta in model_stream:
        code += delta
        t.feed(delta)  # closed stmts launch calls now
exec(code, ns)  # hits return immediately

For the RLM this is one line: from demo.rlm import patch_rlm; patch_rlm().

example.py is an example you can start with for looking how this is done for the RLM.

For arbitrary harness, we provide a simple daemon spec-ptc-daemon that runs the same shadow + store out of process (default socket /tmp/spec-ptc.sock) with four JSON-lines messages:

turn_begin {vars}      snapshot REPL variables into the shadow
feed {delta}           stream tokens; the daemon launches calls
resolve {tool, args}   → hit{result} | miss   (miss: run the tool yourself)
turn_end               evict leftovers, return hit/miss counts
from plugins.client import SpecClient  # ~60 lines, stdlib only — copy it

c = SpecClient()
c.turn_begin({"context": doc})
c.feed(delta)  # per streamed token
hit = c.resolve("llm_query", [prompt])  # result, or None → call it yourself
c.turn_end()

Wrappers in plugins/: Claude Code (PreToolUse), OpenCode, Pi-mono.

Continue your stack

What teams reach for next — and why each earns a place beside spec-ptc. Ranked by curator confidence.

Pairs well with
prime-agent

Self-improving coding/research agent around a Recursive Language Model: persistent IPython as the core tool, programmatic subagents, durable harness state it refines via evidence-backed /refine.

Why it fitsPrime-agent is a Recursive Language Model harness whose programmatic subagent calls inside a persistent IPython REPL are exactly the expensive blocking work sPTC hides behind token generation — the repo's own demo patches an RLM in one line.
deepagents

LangChain's batteries-included agent harness on LangGraph — planning, sub-agents with isolated context, filesystem, shell, skills, human-in-the-loop and persistent memory out of the box.

Why it fitsAny harness that spawns sub-agents from inside generated code gets the same overlap. Deepagents runs planning and isolated-context sub-agents on LangGraph; sPTC's out-of-process daemon and ~60-line client are the generic way to bolt speculation onto a harness like it.
headlong

Persistent-agency agent harness in ~10K lines of Bash: it keeps thinking between messages, thinks by writing shell commands, and one shared mind serves a whole team over Slack or Telegram.

Why it fitsSame lineage: Headlong's `shellm` core is a Bash implementation of a Recursive Language Model, and sPTC is the speculation technique built for RLM-shaped harnesses by the author of the RLM writeup Headlong cites. The payoff applies wherever sub-LLM calls inside a generated block dominate wall-clock; wiring it into a Bash REPL means driving the sPTC daemon over its socket rather than the one-line Python patch.