Repository navigation
Releases
Call4Agents v0.6.0
0.6.0
New (experimental)
-
call4agents crashtest <script>kills your agent at every step, restarts it, and reports which action ran twice,
ran without approval, or never finished. Your agent does not need our guard.call4agents crashtest --demoshows
it on a small agent, without and with the one-line fix. Tested with small real agents on LangGraph, Pydantic AI and
the OpenAI Agents SDK. Every action really runs, many times: use test accounts. -
call4agents scan <path>reads Python source and lists tools that send, pay, delete or write with no approval or
once-only guard. It runs nothing. Results on real projects, with what it gets wrong, are indocs/SCAN_RESULTS.md. -
call4agents auditwrites a signed export: who approved what, when, for which exact arguments, and what ran.
call4agents audit-verifyfails if anything in it was changed. Anyone with the secret can sign a false export, so
this shows the file is unchanged since it was signed, nothing more.
Changed
- SECURITY.md: every report is answered within 24 hours and serious ones are fixed within 7 days.
docs/REVIEWED.mdlists what outside people have reviewed, and what nobody has.
Call4Agents v0.5.3
0.5.3
New
call4agents incident: three approval incidents in a few seconds, each without and with the kit: a double
payment, a changed call, and a "no" that a buggy agent loop ignores. Real processes and real crashes; the bank and
the agent loop are small local stand-ins. Animated in the README. Check K23 keeps its numbers honest.
Call4Agents v0.5.2
0.5.2
Fixed
- Processes that open a new run record at the same moment could fail with "not a usable Call4Agents run record
(database is locked)", because SQLite does not apply its busy timeout to every step of opening a record. Opening
now waits and retries for up to 30 seconds. Check P19 and a mutation. Found by the stress test on Windows.
Version 0.5.1 was tagged but never published: this bug stopped its release. The security fix below ships in 0.5.2.
Call4Agents v0.5.0
0.5.0
New (experimental)
- Approval tickets for the OpenAI Agents SDK (
c4a_oa.tickets(result, tools),c4a_oa.apply(state, decisions))
and LangGraph (c4a_lg.pause(tool, config, **args); the ticket goes in theinterrupt()payload). Checks
T12 and T13 run them against the real frameworks. - One open ticket per call. Pausing the same call again while its ticket is open (not decided yet, or approved
and not used) returns the same ticket, so a LangGraph node that re-runs on resume does not leave a second request.
After the action ran, or after a "no", a new pause asks again (T11).
Fixed
- A named action reused with other arguments is a conflict (issue #1, reported by @krivonosoff161). Calling an
effect again with the samec4a_key(orkey=) but arguments that mean something else returned the first call's
result silently: nothing ran twice, but the caller was told the new call succeeded. It now raisesKeyConflict
and nothing runs. The same key with the same arguments still returns the recorded result; numbers are compared
by value (10, 10.0 and Decimal("10.00") are the same amount). Check K21 and two mutations.
Project
- SECURITY.md (private reporting, acknowledged within 7 days), CONTRIBUTING.md, CODE_OF_CONDUCT.md, ROADMAP.md,
docs/RELEASING.md (how a release is made and how a bad one is rolled back), issue and pull-request templates.
GitHub Discussions and private vulnerability reporting are on. - Docs: "check the outside system" replaced by "get an authoritative answer from the provider": a read that finds
nothing can lag, so it is not proof that an action did not happen (thanks to the discussion in
openai-agents-python#5409).
Call4Agents v0.4.0
0.4.0
New (experimental)
- Approval tickets.
c4a.pause(tool, **args)records that a run waits for a person and returns a ticket;
c4a.decide(ticket, "approve" | "deny", by=...)records the decision for exactly that call. The ticket holds
no arguments (a random id and a MAC), so what may run is read from the record, never from the client. A ticket
the record did not issue, or one that was changed, expired or already decided, raisesTicketRefused.
Pydantic AI bridge:c4a_pai.tickets(result, tools)andc4a_pai.results(decisions). Checks T1-T10 (with the
real Pydantic AI in CI) and five mutations. Chosen because human approval is the most-asked-for area in the
agent frameworks' issues; the cases come from langchain#40491, pydantic-ai#6452 and pydantic-ai#6968.
Improved
- The on-call commands (
status,doubt,resolve,verify,archive) take apostgresql://address too.
They refuse an address with no run record instead of creating one.archivecopies finished runs to a SQLite
file, then removes them. Checks S8-S12. - The multi-machine record is labelled beta in the README.
- README: a 15-line first example with its real output, and a "When something goes wrong" table.
Call4Agents v0.3.0
0.3.0
New
- One run record shared by several machines.
c4a.init("postgresql://...")keeps the record in PostgreSQL
(pip install "call4agents[postgres]"), with the same table, UNIQUE indexes and format check as the SQLite file.
A long action that is still running on one worker is not started again by another (the case in langgraph#7417).
Every machine must pass the same secret; there is no local secret file for a shared record. - Checks S1-S7 (
python -m tests.test_shared_record) with a separate process per machine, and mutations for them.
CI runs them on Linux, macOS and Windows against a throwaway local PostgreSQL.
Fixed while building it
- Approval keys contain a NUL separator, which PostgreSQL text cannot store. The PostgreSQL store escapes it
reversibly (S7); SQLite records are unchanged.
Call4Agents v0.2.1
0.2.1
Metadata only, no code changes: links to the website and the guides (Homepage, Documentation), more keywords and classifiers on PyPI, and a link to the guides in the README.
Call4Agents v0.2.0
0.2.0
New
- Adapters for Pydantic AI, the OpenAI Agents SDK and MCP (
call4agents.adapters.pydantic_ai,.openai_agents,.mcp). They leave the framework's context argument out of the key; plain@c4a.effectrefuses it, because it changes on every call. They also take the run id from the framework: the conversation id, the run context or the MCP session id. Each has a copy-and-run example that CI runs against the real framework on Linux, macOS and Windows. - Undo:
@c4a.effect(undo=...)andc4a.undo()reverse a run's finished actions, newest first. Each undo runs once only, a crash half-way continues where it stopped, and a failed undo stops the walk and is "in doubt" until a person resolves it. Developers asked for this in Pydantic AI issues #9141, #4679 and #7247. exclude=on@c4a.effect: parameters left out of the key.call4agents report: prints your versions and a link to the issue form with them filled in. It sends nothing.- An animated 30-second demo at the top of the README (
docs/demo.svg), built from a realquickstartrun.
Checks added: K20, P18, U1–U6, the adapter checks, and mutations for each (python -m tests.mutations.run_kit_mutations).
Call4Agents v0.1.0
0.1.0 (first public release)
Licence: Apache-2.0. Companies can use, change and ship it, with a patent grant. The NOTICE file must be kept, so we stay credited, and section 6 gives no right to use the project's name.
What it does
- Once-only actions (
@c4a.effect): a crash, retry or resume does not repeat an action. An action interrupted half-way is reported as "in doubt" instead of being repeated. - Approvals bound to exact arguments: one "yes" covers one action,
c4a.denyis enforced, and racing callers on one "yes" run once. - Idempotency keys for outside APIs (
c4a.idempotency_headers(),idempotent_for=). - Record, replay and diff for model calls, keeping result types;
provefor mutation-testing your own guards. - LangGraph / LangChain adapter; the decorator also works in Pydantic AI, the OpenAI Agents SDK and plain Python.
- Commands:
quickstart,selftest,doctor.
For production
- On call:
status,doubt [--fail-if-any],resolve,archive,verify, so nobody has to read the database. - Long-running systems: a versioned record format, secret rotation (
old_secrets=,C4A_OLD_SECRETS), and an atomic secret file for many processes. - Speed: about 1.9 ms per new action on our test machine (one reused connection per thread).
- Clear errors for damaged or foreign record files, network drives, unstable arguments, generators, unnamed lambdas and results that cannot be recorded.
- Late results are recorded and reported, never hidden.
- Safe replay: a crafted record cannot make the decoder call a function.