Repository navigation
Releases: zoolok17/agenttalk
Release list
agenttalk 0.104.0
A team can now share what it learned with another team: one team exports some of its own checked lessons as a pack file, and another team loads that pack from a folder it checked out itself. Nothing is downloaded or sent anywhere by agenttalk. Pack lessons can also carry the date they were last confirmed, so old advice no longer looks new. The release also adds two roadmap sections on research into AI that improves itself (documentation only).
After upgrading, preview the skill update with agenttalk install-skills --dry-run --force, back up any local edits you want to keep, then run agenttalk install-skills --force. The plain command keeps files that differ, so it cannot refresh changed skills. To use a pack from another team, read the pack file first and take out anything confidential, then run agenttalk knowledge pack load <name> --from <folder>.
Added
-
A team can now share lessons with another team as a lesson pack, and load another team's pack
from a folder. Until now a new store could start only with the lessons that ship with agenttalk.
What one team learned stayed in that team's store, and there was no way to hand it over.What you will notice:
agenttalk knowledge pack export --name <name> --out <folder>(with--key
once per lesson, or--tag) writes some of your team's own verified lessons as a pack file, ready
for a person to read before it is shared. Next to it, it writes a provenance file that links each
lesson back to your store; that file stays with your team. Lessons that are not verified, are
retracted, are replaced by a newer lesson or came from a pack are never exported. The export never
publishes, commits or pushes anything, and it refuses to overwrite a different pack of the same name
unless you add--force.
agenttalk knowledge pack load <name> --from <folder>loads such a pack from a folder you checked
out yourself. agenttalk never downloads anything and reads only the lesson files, never roles,
prompts or brief templates. The rules of the shipped packs apply: your team always wins, loading
the same pack again writes nothing, andunloadtakes it back. Outside packs have their own key
prefix and tag, so they can never mix with a shipped pack, and a name that a shipped pack uses is
refused.knowledge pack listshows where each outside pack came from. Before this, a lesson
pack's review and expiry dates always counted from the day it was loaded, so old advice looked new.
Now a pack line may say when the lesson was last confirmed, and the dates count from then. A pack
with a bad line is refused as a whole, the message names the line, and nothing is written.What you need to do: nothing. Read an exported pack, and take out anything confidential, before you
share it.Technical details:
knowledge_pack.pygainsread_pack(name, folder=...),load(..., folder=...),
unload(..., outside=...)andexport(...);cli.pygainspack load --from,pack unload --outsideandpack export. An outside pack's id isext.<name>: keyspack.ext.<name>:<slug>,
tagpack-ext.<name>, ledger entryext.<name>. Shipped pack names cannot contain a dot, so the two
namespaces never meet. The ledger entry gainssource(folder,file_sha256,retired_sha256when
there is a retired file, andcommit, read withgit rev-parse --verify HEADwhen the folder is in a
git checkout). The event schema is unchanged. The optional last line fieldconfirmed_at(an ISO
date or date and time, not in the future) setsreview_afterandexpires_atto 365 and 730 days
after it, and a newerconfirmed_atcounts as a change on reload. The line reader now also refuses a
key or tag with the reservedpack.orpack-prefix, a line that is not UTF-8 or holds an unpaired
surrogate, and a<name>.retired.jsonthat retires a slug the pack still carries, and names the line
for every refusal. Records end only at a newline (_physical_lines), never at U+0085, U+2028 or
U+2029, which the export writes unescaped (_dump_line, shared by the export's checks and its writer).
Before writing, the export reads its own bytes back the way the loader does, and it refuses when the
folder's retirement file is malformed or retires an exported slug; it never changes that file. Export
keeps each lesson's(domain, key)identity: a bare--keyheld by several domains is refused with
the candidates listed, and--key <domain>/<key>names one. Ownership is read from content provenance
(curated_origin), never from the key's spelling, so a team lesson keyed likepack.<x>:<y>exports.
Supersession follows the store, which applies asupersedeskey in every domain. The report carries
provenance_changednext tounchanged, and an existing non-UTF-8 pack or provenance file is
refused with its path. Export slugs are the key in lower case with each run of other characters
turned into one dash (cut to 60 characters with an 8-character hash ending); two lessons that would
share a slug refuse the export. Tests:
tests/test_knowledge_pack_outside.py. Docs:docs/USER-MANUAL.md(Share lessons with another
team) anddocs/playbook/learning.md(L5).
agenttalk 0.103.0
New teams get clearer setup and restart advice, more useful lesson searches, and fewer repeated refusals when saving what they learned. Leads are reminded when a teammate is waiting for a decision, and can pass that decision on with one command. New skills, the team playbook and the migration guide help teams agree what done means and carry lessons into their next project.
After upgrading, preview the skill update with agenttalk install-skills --dry-run --force, back up any local edits you want to keep, then run agenttalk install-skills --force to refresh the bundled skills. Restart wrapped agents after switching their tool runtime. Existing teams can use agenttalk knowledge pack load migration to load the bundled migration lessons; new stores receive them at setup.
Added
-
The team playbook:
docs/playbook/collects the standing team rules and the reasons behind them (#534, #547). -
A shared meaning of "done" for every task: the new
definition-of-doneskill. Teams
lost time when "the work is finished", "the product is accepted" and "it may be released"
were taken for one thing. The skill keeps them apart and gives every task the same five
things to show when it is handed over: what was asked and what came out, the exact thing
delivered, the checks that really ran, what is left open, and who acts next. Bigger or
riskier work adds rows by kind (review, QA and test, documentation, investigation, bug fix,
refactor, CI fix, feature, whole project or release, one migration slice, a whole migration). A check that could not
run stays open until the person with authority records a reduction of scope; the rules
are pinned when a task is assigned, and a lesson changes them only after review. It
reuses the existing evidence fields, thecloseflow and the release-readiness review
instead of adding new ones, and a project keeps its own rules in a short overlay file.
Its replay on six finished jobs from this repository is in
docs/research/DOD-REPLAY-2026-10.md.
Technical detail:src/agenttalk/skills/devkit/definition-of-done/(SKILL.md,
references/migration.md,references/project-overlay.md), policydefinition-of-done@1,
evidence profilesproduction-handoff,review-result,qa-resultandplanning-artifactby task kind; routing and the skills tables list it. -
A lead is now reminded of the decisions it still owes to seats that wait for them.
When a seat says it is waiting for a lead's decision and the result it waits for has
finished, the lead used to hear about the result and then nothing more; the seat could
wait for a long time. Now agenttalk works out, from the messages themselves, which
hand-offs are still owed. It shows them after the lead reads messages and on every turn of
a wrapped lead, and reminds the lead again if the first reminder is ignored. A new command,
agenttalk relay result, hands the decision over exactly once (also when it is run twice
or two processes race), or closes it as not needed or unresolved. This is best effort and
covers only seats that said they wait: a seat that never said so is not seen. Message
cleanup (compact) no longer removes what an open hand-off depends on. A second new
command,agenttalk lead-routine, records which parts of the lead's routine were done
and by what, and keeps the parts that agenttalk cannot check (handover note, machine
resources, scheduled timers) apart so they are never mistaken for covered.
A finished hand-off stays finished when old messages are cleaned up in several steps, and a re-asked
request no longer offers its old answer. Only the command's own message closes a hand-off, and the
routine record keeps the sweep's findings and the lead's own word apart for every part.
A hand-off is no longer closed by an older one, a cancelled or incomplete request no longer produces
one, a mistyped seat name inrelay_tois refused when the request is sent, and the reminders stay
fair however many hand-offs are open. A seat that waits again can be answered again, the operator is
told about an overdue hand-off at the third reminder and then once a day, and a request id with a comma
is refused when the request is opened. A hand-off for an older wait never counts as the answer to a newer
one, even when the two cross while a command is running. A hand-off is refused unless that seat has an
open wait for it (a mistyped seat name, or a wait the seat cancelled), and a cancelled wait stays cancelled.
(Technical detail: derived obligations inlead_relay.py;Store.send_operationgained a
precheckrun inside the publication lock;Store.archive_messages_batchedrecomputes the
protected floor under the rank-100 and rank-160 locks; routine record in
lead_routine.py; designdocs/DESIGN-lead-loop-default.md.) -
A new team starts with the migration lessons, and
agenttalk knowledge packloads, lists and
removes lesson packs. What several practice migrations taught us (124 short lessons: how to
move a codebase to a newer framework, language or platform and prove that it still behaves the
same) is now part of agenttalk, together with a plain-words guide,docs/MIGRATION-PLAYBOOK.md.What you will notice:
agenttalk initnow loads themigrationpack into a store it creates
and says so; pass--no-packsto start empty. Runninginitagain on a store that already exists
never loads a pack and never undoes a--no-packsor anunload. The lessons show up inagenttalk knowledge search --type lessonand carry the key prefixpack.migration:and the tagpack-migration. They always rank
after your own lessons, and they never take one of the five lesson slots that agenttalk puts into
an agent's turn, so an agent finds them when it searches, not before.agenttalk knowledge pack list,load <name> [--dry-run]andunload <name>manage packs later. Your team always wins:
a pack lesson you retract, replace with a lesson of your own, or republish is never brought back
or changed by a later load or upgrade, even after anunload, and loading the same version twice
writes nothing. The prefixpack.is reserved:knowledge publishrefuses a new key that starts
with it. A lesson of your own whose key already starts withpack.keeps working as before.
agenttalk knowledge pack listcounts from the store (live, retracted by the team, changed by the
team), not from the loader's bookkeeping.What you need to do: nothing. An existing store gets the pack only if you run
agenttalk knowledge pack load migration.Technical details: new
knowledge_pack.pyand the data file
src/agenttalk/knowledge_packs/migration.jsonl. The file is part of the wheel;dev-gate.jsondoes
not list it (the gate pins its list of wheel resources), so a test builds the wheel and checks that
the pack is inside (it is skipped where the build toolhatchlingis not installed).
The loader writes a publish and a curate event per lesson (author, owner and curator
agenttalk-pack, domainprocess;evidencebecomesevidence_ref; review and expiry dates are
relative to the load). The pack name and version are not in the events: they live in the ledger
.agenttalk/knowledge/packs.json. Whose a lesson is, is read from the store: every event the loader
writes carries two marks, the authoragenttalk-packandauthority.resolved_fromset topack.
No ordinary command can set the second one, so a member of the team who is calledagenttalk-pack
cannot pass for the loader (the name is also now refused for new rosters and new publishes). Any
later event by someone else (a republish, a retraction, a re-verification, a lesson that supersedes
it) makes the lesson the team's for reload and unload. For ranking and for the injected slots only
the content counts: a lead verifying an unchanged pack lesson does not turn it into a team lesson,
a team republish of the same key does, once it is verified (while it is only a proposal, readers
still show, and rank, the verified pack text as pack content). So a load or unload that
is cut short before the ledger is written is recovered by the next run, which adopts what it finds
instead of writing it twice. A later pack version may carry<name>.retired.json; keys it retires, and keys it
removes, are retracted unless the team touched them. Inknowledge.pythe lesson rank gains a
first tier (team lessons before pack lessons, by where the displayed version's content came from: each event
carries the loader's two marks of the publish it comes from; not the key, the name or who verified it
last) and
lesson_context.select_lessonsskips pack lessons. -
A new skill,
thinking-games, for the few moments when a different way of thinking helps.
Some decisions get better when someone looks at them from a different angle. The new skill gives
agents short thinking games, and roleplay cards to think from, for a few named moments only: at
the start of a new design, before it is challenged (the challenge skill is where an independent
agent asks whether the work should be done at all); after two failed attempts on the same
assumption, outside a round of fixes ordered by a review (then only the "reality probe", which
ends in a real test); and as a side round on product ideas, after agents have given their ideas
the plain way. It is not for routine work, fixes ordered by a review, releases or every task. One
game per moment is enough (in a team round, one per pair or group).How it works: two lists of ideas are written from the same short description of the decision,
one the usual way and one with a game. The second list is written by another agent, or by a fresh
one that never saw the first list; when that is not possible, the round is labelled "not
independent". Every idea says what it would do, what it should improve, how i...
agenttalk 0.102.0
In short: a team is easier to watch, an agent that has run for a long time can be given a
fresh start with one command, and three faults that stopped people are fixed.
agenttalk overview prints the dashboard's Overview in the terminal, in plain words, and the
new /agenttalk (Claude Code) and $agenttalk (Codex) skills run it. agenttalk status and
the dashboard show how large each agent's conversation has grown and warn before it gets
expensive; agenttalk session fresh then starts that agent's next turn on a new conversation
without stopping it. Fixed: agenttalk backup works when the team folder and the backup
folder are on different drives; an agent that is stuck waiting on a message it cannot run can
be stood down with agenttalk release; and on Linux and macOS a background agent starts from
a normal virtual environment (python3 -m venv), so the --copies workaround is no longer
needed. After upgrading, run agenttalk install-skills to get the two new skills.
Added
-
agenttalk overviewshows how the team is doing on one screen, and/agenttalkand$agenttalkrun it for you.
It is the terminal's version of the dashboard's Overview.What you will notice: a new command,
agenttalk overview, prints about one screen in plain words:
what needs attention, who is waiting for whom, how each agent is doing, and whether the release
checks are holding anything up. In a Claude Code seat you can type/agenttalk, and in a Codex
seat$agenttalk; both only run the command. It is read-only: it never moves a message cursor,
changes anything, wakes an agent or calls a model. The paid-model spend is left out unless you
add--enable-budget, because that ledger covers the whole machine and any seat can run the
command.What you need to do: nothing. Run
agenttalk install-skillsto get the two new skills.Technical details: new
overview.pyrenders only what the dashboard's own builders return
(web.build_state,web.build_attention,web.build_gates), derives nothing, and leaves out a
field the builders leave out.--jsonprints those three payloads (plusbudgetwith the flag).
Output is plain ASCII, so it reads the same on Windows, Linux and macOS. -
agenttalk statusand the dashboard now show how large each agent's conversation is, and warn
before it gets expensive (#475, part 1). An agent that runs in the background keeps one
conversation for as long as it lives, and every turn sends all of it again, so a long
conversation makes every turn, even an idle check, cost more.What you will notice: each agent's row in
status(and its Capacity card in the dashboard) has a
new line saying either how many tokens of context its last turn used, when its AI reports that,
or how many turns it has run in total. It always says which of the two it is. The turn count is
cumulative: a fresh start does not reset it, so it can include earlier conversations, and the
warning says so; only the token figure describes the current conversation. Above a limit the line
carries a warning. The warning is advice only: nothing is restarted,
stopped or changed, and no message is sent. The limits are 150,000 tokens for Claude, 190,000 for
Codex, and 300 turns for either; the token limits sit at about three quarters of the context
windows those tools report, and 300 turns is well above the 170 to 230 that healthy agents reach
and far below the 830 behind the report.What you need to do: nothing. To change a limit, add
conversation_warn_tokensor
conversation_warn_turnstosupervisor.json, either one number for both tools or
{"claude": n, "codex": n}; an unusable value is ignored. Starting an agent on a fresh
conversation with one command is the next part of #475 and is not in this change.Technical details: new module
conversation_size.py; additiveconversation_sizeobject
(basisiscontext_tokensorturns_total, plusvalue,limit,warn,cli) in
status --jsonand in each agent of/api/state, left out when neither figure is known. The
token figure iscontext_tokensfrom the agent's capacity snapshot (an expired reading counts
as absent); the turns figure isturnsfrom the wrapper session record, shown only when the record has one (an absent counter is unknown, not 0). A reading of 0 is a reading. Limits must be positive whole numbers.supervisor.jsonis read the way the supervisor reads it (a byte-order mark is fine), and the dashboard andstatusresolve each agent's tool the same way. Read-only. -
Start an agent on a fresh conversation with one command (#475, part 2). An agent that runs
in the background keeps one conversation for as long as it lives, and every turn sends all of it
again, so a long-lived agent gets slower and costlier. Until now the only way out was editing
the agent's session record by hand.agenttalk session fresh --for <agent> --reason "..."now
asks the agent's own wrapper to start its next turn on a new conversation. The wrapper does it
between turns: at once if the agent is idle, or right after the turn that is running. Nothing is
stopped and no file is edited by the command. The old conversation is never resumed, the request
is applied exactly once, and a second request while one is waiting is refused.agenttalk status
showsfresh=pendingand thenfresh=applied(with the reason and the turn count it started
from, instatus --json). The old session record is kept beside the new one. The agent itself,
a lead or the operator-facing agent may ask. Works for Claude and Codex agents. The agent starts
without its old conversation, so it should leave a note of what is next before it is asked to
start fresh; the automatic handover note is planned (#475, steps 2 and 3).
Technical detail: the wrapper loads<agent>.wrapper-session.jsononce and saves its own copy,
so an outside edit could be overwritten or ignored. The command therefore only writes a
<agent>.fresh-requestmarker.wrapper/session.pyapply_fresh_requestis called from the
wrapper's own thread before each turn is built (both drives) and on each idle poll: it resets the
in-memory session (a new Claude session id, or a cleared Codex thread), saves the request id with
the reset, and only then clears the marker, which is what makes it apply once even after a crash.
The outcome is recorded in the session record (fresh_request_*) and projected by
Store.read_fresh_statusand, as the reset reasonfresh_requested, by the dashboard reader.
Fixed
-
agenttalk backupnow works when the team folder and the backup folder are on different drives
(#505). A backup first checks whether it can make "hard links" (a second name for the same file,
which is fast and uses no extra space) and otherwise copies the files. That check linked two test files
inside the backup folder, so it never noticed that the team's own files were on another drive, and the
backup then stopped with an error (WinError 17on Windows, "Invalid cross-device link" on Linux and
macOS).What you will notice: before this, a team on one drive (for example
D:) with the default backup folder
on another (C:), or on a separate data disk, got an error and no backup. Now the backup completes. It
copies the files, andagenttalk backupsaysmode: copy (no hardlink support); the backup's
manifest.jsonsays"hardlink_used": false. On one drive nothing changes: it still uses hard links.What you need to do: nothing. Until you have this version you can set
AGENTTALK_RECOVERY_DIRto a
folder on the same drive as the team folder.Technical details:
recovery._probe_hardlink_supportnow links one real store file into the backup's
staging folder (and removes the link) instead of linking two probe files inside it, and
recovery._clone_treecopies a file whose link fails and returns whether every file was linked, so
hardlink_usedis true only then. Tests:tests/test_recovery.py(a forced cross-deviceos.link, a
link that fails after the probe passed, and a same-filesystem control). Checked for real on Windows
with the store onD:and the backup folder onC:. -
A parked agent can now be stood down with
agenttalk release(#488). An agent whose next message it
cannot run is "parked": it keeps that message at the front of its queue and waits. Until now arelease
sent to a parked agent was never read, so the agent kept running, and the only way to stop it was to kill
its process, which cannot be done safely from outside (it may be starting a paid model call at that
moment). Now the agent notices a valid release waiting behind the parked message
and stands itself down between turns, the same as an idle agent. It starts no turn after it has accepted
the stand-down. The parked message itself is not touched: it stays first in the queue and unread until
something resolves it. The release also stays unread for now (an agent has one reading position, so
reading the release would also have read the parked message);agenttalk statusshows
stand_down=honouredfor it until it is reached. When the agent is started again, it does not stand down a
second time for that release: it consumes it silently and runs.
Technical detail:wrapper/loop.py_stand_down_behind_held_headruns right after the head's attempt
record is read and before any park, re-probe or drive. It applies when the head is held (a sticky
config_blocked, a usage-limit or provider park, or a gateway hold that is re-driven every poll, which is
remembered inheld_head_id). It validates the release withclassify_loop_control(same authority rules
as an idle release), records its id withStore.record_stand_down_honoured(state/<agent>.stand-down.json,
20 entries, written before the loop returns; if it cannot be written the agent keeps running)...
agenttalk 0.101.1
In short: one fix for the paid gateway. When the model pauses for a long time in the middle
of a reply, the gateway now waits up to ten minutes for the next piece instead of two. Such a
call used to end as an "uncertain" paid attempt that stopped every gateway seat until someone
settled it by hand. The gateway also writes one log line for each reply it streams, so a
future stall shows what happened. Nothing else changes: LiteLLM, the spending ledger and the
prices are as before, and the installed skills do not need refreshing.
Fixed
- A long silent model reply no longer ends as an uncertain paid attempt (#424, part A). The
gateway's front door gave up when the model sent nothing for two minutes. That left the paid
call "uncertain" and stopped every gateway seat until someone settled it by hand. Once a reply
has started, the front door now waits up to ten minutes for the next piece (connecting and
starting the reply still wait two minutes). It also writes one line per started reply to
stream-waits.jsonlin the gateway's state folder: the longest wait for a byte, the total
time and how the call ended, so the next incident shows what really happened. A reply that
stays silent for more than ten minutes is still marked uncertain, exactly as before; the
LiteLLM version, the ledger and the prices are unchanged.
Technical detail:FrontConfig.stream_idle_timeout_seconds(STREAM_IDLE_TIMEOUT_SECONDS,
600 s) is applied to the upstream socket after the response headers arrive; the front keeps
the socket from beforegetresponse()becausehttp.clientdrops it on "Connection: close".
request_timeout_seconds(120 s) is unchanged for connecting and waiting for the headers.
GatewayFront.stream_wait_observerreceives one record per started reply, andStreamWaitLog
(bounded to 1 MiB, one rotation) writes it.
agenttalk 0.101.0
In short: the checks that decide whether a team's work is finished are stricter and say more
clearly what is missing. A seat that runs through the paid gateway can no longer satisfy any
required review, and an acknowledgement counts only while its author is still an active,
trusted seat: a finished result that rested on a reviewer who has since left now needs a
current reviewer to acknowledge it again (an acceptance close whose runner has left needs a
new attempt instead, as described below). The check before an irreversible step names
exactly what holds a request back and also stops on an outdated request. When agenttalk gateway start fails before the task-start request is accepted, the gateway keeps its stop
file; after that point the command says the gateway may be starting and how to check and
stop it. agenttalk scratch store sets up a throwaway store that commands in that shell
cannot leave (an ordinary folder alone does not: set it up with that command). The
documentation set gained a license, a technical overview, a page on roles, skills and
procedures, and operator procedures that put each safeguard before the step it protects; the
source package now ships the documents its own tests read. After upgrading, refresh the
installed skills as described under "Lead skills" below.
Added
-
The repository now carries its license. agenttalk has always been offered under the
MIT license (the package says so), but the repository had no license file, so GitHub
showed "no license", which by default means nobody may reuse the code.What you will notice: a
LICENSEfile with the MIT text and the line "Copyright (c) 2026
the agenttalk authors". GitHub now shows the MIT license, and the installed package
carries the same file. Nothing to do. -
A technical overview of how agenttalk is built (
docs/OVERVIEW.md). One new page
that explains how agenttalk is put together, for someone who will run or extend it.What you will notice: a new page,
docs/OVERVIEW.md. It shows the parts and how they talk
to each other, where the data lives under.agenttalk/(and what a reset keeps), a
message's life from send to reply, how the supervisor, wrapper and agent processes relate,
how the console and the paid gateway work, and which promises hold and which do not. It has
five diagrams, a short list of the words it uses, and an appendix of interfaces. Nothing in
the program changed, and no other page was changed.What you need to do: nothing.
Technical details: the page was checked against the code of release 0.100.0. It states the
Python versions the project's tests run on (3.10 to 3.13 on Linux, Windows and macOS). Where
an older page and the code disagreed, the page follows the code. -
One page says who does what in a team, which skill to use, and the steps the team follows.
This information was spread over several older pages, some of them out of date. It is
the first page of the smaller documentation set the operator asked for on 2026-10-10.What you will notice:
docs/ROLES-SKILLS-PROCEDURES.mddescribes each role, with what it
does, what it must never do and how it hands work on:- the operator and the liaison;
- the lead, developer, reviewer, tester, architect and challenger;
- a seat that works through the paid gateway.
It has one entry for every shipped skill, saying when to use it. It also gives current
step lists for handing out work, the review cycle, the merge gate, the release ritual, the
challenge, the acceptance pass, the lessons lookup, capturing lessons and scratch hygiene.
It states the merge rule the team now follows: one recorded GO on the exact head commit, from
a reviewer who did not build the change, with green CI and every automated P0, P1 and P2
comment triaged. It retires the older rule of two reviewers both re-approving the final commit. Its
facts were checked against the code of this version.What you need to do: nothing. The older pages stay until a later change moves them to an
archive.Technical details:
tests/test_roles_skills_doc.pyfails when a shipped skill has no
entry on the page, or the page names a skill that does not ship. A shipped skill is a
Claude Code file insrc/agenttalk/skills/claude/or a folder with aSKILL.mdin
src/agenttalk/skills/codex/orsrc/agenttalk/skills/devkit/. -
An operations guide brings runtime upgrades and rollback, supervisor hosting,
paid-gateway setup and spending limits, backups, recovery, logs and attended
cleanup together indocs/OPERATIONS.md. It distinguishes shipped commands
from steps that still need an operator or maintainer.
Fixed
-
The check before an irreversible step now says what is holding a request back. With both
--epochand--gates, a request that was still current but held only by a gate at HOLD was
reported as "pre-epoch", and the agent was told to ask for the request again. It now says
hold, names the gate and says not to act until it is GO (agenttalk gate check); a request
from before the latest epoch barrier is still reported as one, and when both apply, both are
named. The exit codes are unchanged (cmd_checkinsrc/agenttalk/cli.py). -
The source package now holds the documents its own tests read. The tests shipped in the
source package read the new roles page, two pages underdocs/ops/and the staging example
underdocs/examples/, but the package left those files out, so those tests failed when run
from it. The files are now included, with the new overview page, and a new test
(tests/test_sdist_docs.py) fails when a test names a file underdocs/that the package
leaves out. -
The check before an irreversible step now also stops on an outdated request (#448).
Before a merge, release, deploy or deletion, every seat is told to runagenttalk checkon
the request it is acting on. That check looked only for a withdrawn request and for gates on
HOLD. When the team had since moved to a new epoch (someone ranagenttalk barrier bump),
a request sent before that still passed, so a seat could act on instructions the team had
already set aside.What you will notice: the wrapped-turn prompt, the lead, listen and handoff skills (Claude
and Codex copies), the README and the agent, user and new-user manuals now give the check
with--epoch. A request sent before the latest epoch
barrier now makes the check exit 3, and the seat stops instead of going ahead. The seat needs
no epoch value of its own: the check compares the epoch stamped on the request when it was
sent with the current one.What you need to do: wrapped seats get the new prompt once their wrapper runs this version.
A seat run by hand keeps its older installed skill files, because the installer leaves a
changed file alone: preview withagenttalk install-skills --no-devkit --dry-run, back up
local edits, refresh on purpose withagenttalk install-skills --no-devkit --force, then
start a new session.Technical details:
src/agenttalk/wrapper/prompt.py(_DEFAULT_RULES, the "Before any
IRREVERSIBLE action" line), the six skill files,README.md,docs/AGENT-MANUAL.md,
docs/USER-MANUAL.mdanddocs/AGENTTALK-NEW-USER-MANUAL.md;check --epochis evaluated
by_epoch_verdictinsrc/agenttalk/cli.py. The newtests/test_irreversible_check_text.py
pins the full command in the prompt (both shells) and in every skill, that each Claude and
Codex pair says the same thing, and that every check example on those four pages names
--epoch;tests/test_skill_lint.pynow pins--epoch --gatesfor the lead skills. -
A seat that runs through the paid gateway can no longer give a required sign-off of a sign-off set (#447).
Such a seat (an "external worker", a cheaper outside model with a narrower level of trust) was
kept out of sign-off lists only at the moment the roster changed. If the sign-off policy or the
domain lists were edited by hand afterwards, a close could list that seat as a candidate and
count its sign-off.What you will notice:
- A close now leaves a paid gateway seat out when it works out who may sign, so its sign-off
is refused when given (close acksays why and records nothing, even with--override, and
close signoffs overrideis refused for such a seat too) and is never counted, even if the
record was edited to contain one. - An override recorded earlier now counts only while the seat that recorded it is still on the active
roster and is not a paid gateway seat, the same test a signature already passes. If that seat was
since reclassified as a paid gateway seat, retired, removed or renamed, the override is ignored as if
it had not been recorded: the close goes back to HOLD (and says so) until a trusted seat signs, which
then lets it through, or a current trusted lead records the override again. This deliberately turns
an older GO that rested on such an override (for example one by a lead who later retired) into a HOLD. - Other candidates are not affected: a trusted seat in the same role or group still satisfies
the sign-off. If the paid seat was the only candidate, the close stays on HOLD with the plain
reason "its only candidate(s) run through the paid gateway (external workers), which cannot
give a sign-off; add a trusted seat to the candidates (or override to escape)". close check(text and--json) andclose signoffs planname the seats that were left out
(signoff_exclusionsandexcluded_external_workersin the JSON); they show seat names only.- A close record whose stored sign-off state has the wrong shape (an override list that is not a table,
a sign-off set without a text id, an ack whose author is not text) now gives the normal "malformed
close record" HOLD instead of a crash. - The roster still refuses to name a paid seat as a can...
- A close now leaves a paid gateway seat out when it works out who may sign, so its sign-off
agenttalk 0.100.0
In short: closing a terminal window can no longer stop the gateway: its scheduled task now
starts Python without a console window, and gateway run writes its own messages to a log
file. Each machine that runs the gateway needs a one-time task update, with the steps in
"Closing a terminal window can no longer stop the gateway" below; the ledger, the price policy
and the spend checks are unchanged. Team members now look in the team's lessons once before
building, fixing or reviewing. Leads can release one finished worktree after merging
(agenttalk janitor --release). Team notes work before a domain registry is set up, scratch
cleanup checks its starting folders and their parents, a wrapped seat always replies under its
own name, and documentation-only pull requests can skip the long test queue.
Added
-
Team members now look in the lessons once before real work. Before building, fixing or
reviewing something, a member searches the team's lessons for one concrete word from the task
(for examplejunction), once, with one retry using another word only if the first search found nothing. The word goes last, after--, so a word that looks like an option is still read as the word. The search only reads; it
never touches the inbox. A member names a lesson in its reply only if the lesson changed what it
did, and keeps three cases apart: nothing found, the lookup failed (never written down as
"found nothing"), and read but not useful. A failed lookup never stops the work. The wrapped-turn
instructions, the listen skill (Claude and Codex copies) and the lead skill's brief guidance say
so, anddocs/ops/lessons-lookup.mdnames the rule, its start date and the seats that already
did this by habit, so the lessons-use trial can measure reported use under one fixed rule.
A search that reports a problem with the lesson store counts as incomplete, not as "found
nothing". A hit whose preview is cut off (it ends in...) is read in full, once, before it can
change a decision. For that read,agenttalk knowledge searchhas a new small option,--key
(with--domain), which returns exactly the lesson with that key, so other lessons that only
mention the key cannot push it out of the result. Several lessons are reported in one
comma-separated field. Wrapped members get the rule automatically after the wrapper is restarted on this
version. A member run by hand keeps its older installed skill file, because the installer
leaves a changed file alone: preview withagenttalk install-skills --no-devkit --dry-run,
back up local edits, refresh on purpose withagenttalk install-skills --no-devkit --force,
then start a new session.--no-devkitkeeps the update to the bus skills; without it the
installer would also overwrite the development skills, which sit in other folders. The steps
are in the policy page. -
Release one finished worktree after merging. Leads can use
agenttalk janitor --release <path>to remove a clean, unused checkout while
keeping its branch and commits. The command fetches the remote default branch
and refuses when exact ancestry, files, links or activity records cannot be
checked safely. Squash merges stay in place.--release-reportlists eligible
checkouts and sizes without deleting them; both lead skills now include it in
the daily routine. Hidden Git edits and ambiguous launch folders prevent release;
both supervisor state locations are checked. The guidance explains the need to
stop other users and the limits of deletion checks on each platform.
Stale file monitors cannot hide edits, nested repositories with capitalised
metadata names are kept, and unrelated older lane records no longer block release.
Bare repositories inside caches are kept too. Tracked files are compared by
content, so matching file sizes and times cannot hide unfinished edits. -
Permanent checks for mistakes that kept returning in usage readings (#301).
Contributors can now run a small set of checks across publication and display paths,
including deliberate faults that prove the checks detect a wrong account or an expired
figure. A new danger-area page names other fragile areas and their existing guards.
The checks include recorded events and the command and web displays. They also
document an open checkpoint problem (#408), whose fix remains separate.
This changes contributor checks and guidance, not runtime behavior. Nothing needs to
be changed in an existing team.
Changed
- Documentation-only pull requests can avoid the long test queue. Before
this, every PR push ran the full test matrix and the extra Windows timing
trial. Now changes to prose that tests do not use run the documentation and
safety checks, and the trial runs only after pushes to master. Documents used
by tests, including README and CHANGELOG, still take the full path. Code PRs
keep the full test matrix; master keeps every check. Contributors do not need
to change how they submit a PR. Technical details: the file rule and the
result reported bydev-gate aggregateare documented indocs/DEV-GATE.md.
Fixed
-
Closing a terminal window can no longer stop the gateway. The gateway's
Scheduled Task used to start Python in a console window. On 2026-10-08 a Windows
Terminal update closed its windows, the gateway ended with it, its automatic
restart did not bring it back, and the gateway stayed down for 16 hours.What you will notice: before this, the task started
python.exe, which opens a
console window. Now it startspythonw.exe, the same Python from the same folder
without a window, and LiteLLM starts without one too. With no window there is also
nowhere to print, sogateway runnow writes its own messages to a log file next to
the LiteLLM log, set up before the gateway code loads. Without that, an error message
would itself crash the run, and a failure while loading would leave no trace.
task-installrefuses, naming the folder, whenpythonw.exeis missing, and
task-install,gateway startandgateway statusall refuse or report a launcher
with no windowless twin, such aspython3.exe. A task installed before this change
shows up ingateway statusas out of date, with the steps to update it; status only
reports and changes nothing.gateway startandtask-installrefuse the old task
with the same steps.task-installnever overwrites a registered task: Task Scheduler
cannot replace a task only while it is still the one agenttalk checked, so you end and
remove the old task yourself.gateway stopaccepts the old and the new task from
eitherpython.exeorpythonw.exe.What you need to do: once, on each machine that runs the gateway, run
agenttalk gateway stop --timeout 30, thenschtasks /End /TN <task>andschtasks /Delete /TN <task> /F(the task namegateway statusshows), thenagenttalk gateway task-install, thenagenttalk gateway start, and checkagenttalk gateway status.
Run the agenttalk commands with the Python runtime that installed the task, after
updating agenttalk in it: the old task is recognised only in that runtime's folder. On
Linux nothing changes.Technical details:
src/agenttalk/ovh_gateway_service.py(windowless_task_identity
and_backend_identityfor the Windows backend only,_registered_with_consoleand
_task_update_stepsfor the refusals, the two-formstop_task,CREATE_NO_WINDOWfor
LiteLLM),
src/agenttalk/gateway_run_log.py(route_missing_output_to_log, called from
src/agenttalk/__main__.pyforgateway run); status reports the errors
task_console_launchandtask_launcher_unsupportedand the fieldtask_update; the
run log is%LOCALAPPDATA%\agenttalk-ovh\gateway\gateway.log. The ledger, the price policy,
the spend checks and the binding are unchanged. See "The task runs without a console
window" indocs/QWEN-OVH-TRIAL.md. -
Team notes work before a domain registry is set up. Pointers, gotchas,
seams and decisions can now use--domain processon a bus without
.agenttalk/domains.json, with the same review rules as process lessons.
Non-lesson notes still need an explicit domain. Buses with a registry keep
their existing rules and note format. Unknown-domain errors now list the
available domains and explain how to add one. -
Four wording fixes in the shipped documentation and the lead skills (#362, #363, #355,
#312). No behavior changed; the text now says what the code already does. The lead
skills' "check before an irreversible action" example now shows--gates, so a lead
following it word for word gets warned when a gate says HOLD instead of only when a
request was rescinded (#362). The README'sackrow now separates its two forms: without
--to-requestit moves a cursor, with--for <seat> --to-request <id>it closes that
request's thread for that seat (a work order, a review, a proposal or a question), records the closure permanently, and does not move the cursor (#363). The lead skills no
longer say a lead may never start a teammate; a lead can set up the team and start the
supervisor when asked, but still never starts a teammate's own assistant directly,
outside the supervisor or the wrapper (#355). And the gateway guide now states that its
amounts are in EUR excluding VAT (#312). The policy data itself carries no tax label yet,
so #312 stays open. -
A wrapped seat that follows its reply instructions now always replies under its own
name (#354, #178). The instructions the wrapper printed gaveagenttalk replywith no
--from, and the wrapper did not tell the seat's own process who it was. A seat whose
settings did not happen to carry its name could stop with "no agent i...
agenttalk 0.99.0
In short: this release makes the usage readings real. agenttalk capacity, each seat's
capacity file and the dashboard now show each account's actual 5-hour and weekly usage, say
plainly when a reading is old, and never show one account's usage under another seat's name.
The dashboard now refuses requests that are not addressed to it as a local program, so a web
page you have open can no longer read it through a trick called DNS rebinding.
agenttalk janitor --apply no longer forces a delete. The dev gate records how long each test
took, and Windows test runs get more time for a month. The gateway and its ledger are unchanged
in this release, so upgrading needs no extra step.
Changed
-
Every test run in the dev gate now records how long each test took, and Windows test
runs get more time for a month (#378). On Windows, the gate's full test runs had reached
their two-hour limit: on 2026-10-06 one was stopped at 90% with no failure, and its twin
passed 15 seconds under the limit. No per-test timings existed to decide what to change.What you will notice: before this, a test run's log listed only skipped tests and the
result. Now it also lists the time of every test's setup, call and teardown, slowest first,
before the result line. That adds about 3.5 MiB to each log, well under its 16 MiB limit. A run
stopped by its time limit says its per-test durations are unavailable, so it is never read
as zero. Windows test runs may now take 9,000 seconds instead of 7,200, and the Windows CI
job 330 minutes instead of 270. Linux and macOS stay at 7,200 seconds and 90 minutes, and
no individual test's time limit changed.What you need to do: nothing. The Windows margin is temporary: it expires on 2026-11-06,
by when the new timings should show how to split or speed up the Windows runs. The reason
and the date are recorded next to the values (windows_timeout_reasonin
dev-gate.json, and the comment in.github/workflows/tests.yml).Technical details:
dev-gate.json(pytestargsadd--durations=0 --durations-min=0;
newwindows_timeout_seconds9000 andwindows_timeout_reason);src/agenttalk/dev_gate.py:- the manifest contract now pins the four pytest arguments;
_validate_windows_pytest_limitaccepts the Windows value only together with its reason,
and never belowtimeout_seconds;_pytest_timeout_secondschooses it on Windows (a CI leg is refused unless it runs on its
declared OS);run_commandtakes atimeout_note, and pytest runs pass
PYTEST_DURATIONS_UNAVAILABLE.
The Windows job ceiling is in
.github/workflows/tests.yml, anddocs/DEV-GATE.mdhas a
new "Per-test durations and time limits" section. Tests intests/test_dev_gate.pyand
tests/test_dev_gate_workflows.pyinclude a real pytest run (the final result line stays in
the 2,000-character diagnostic) and a real killed run.
Fixed
-
Usage readings are real again, say when they are old, and are shown per account (#301).
agenttalk capacityand the per-seat capacity files say how full each seat's 5-hour and
weekly usage windows are. On the desktop fleet none of those numbers was real: every Claude
seat showed the same reading from 3 June, every Codex seat had none, and the files looked
fresh because they were rewritten every minute. A lead deciding whom to give work to was
shown old or missing numbers that looked current.What you will notice, for Claude seats: before this, a seat's reading came only from a
status-line file that had not been written since June, and it was shown as if it were
current. Now a wrapped Claude seat records its own rate-limit messages from Claude. They say
whether a request was allowed and, when they include them, how full each window is. A
message without a percentage is recorded without one, and a message that names no window
(an ordinary turn's "allowed") is kept as the latest verdict; agenttalk never makes up
either. A malformed figure in such a message is ignored and never stops the seat's turn,
and a reset time outside any real date is dropped, so it can no longer break the web console
oragenttalk status.
The status-line file is only a fallback, read from the same Claude config folder the seat's
Claude uses. A saved reading remembers the account it was taken under and is dropped, never
relabelled, when the seat runs under another folder or provider, so a gateway seat is never
shown the operator's Claude numbers. With no source at all, it says "Claude capacity source
not configured" instead of a number. When Claude refuses a turn because a usage limit is
reached, the seat publishes that reading right away, as it starts waiting, not only at its
next quiet minute. A manualagenttalk capacity refresh --for <seat>run by the seat itself
reads its own folder and provider, found the same way its wrapper finds them. Run for another
seat, it never reads a folder of the shell that runs it, because that shell's~/.claudeand
CLAUDE_CONFIG_DIRsay nothing about the other seat's. It publishes that seat's own saved
reading again, under the account its wrapper bound, or reads the--statusline-pathyou give.
A folder is read only when it matches the account of the seat's saved reading. Otherwise it
publishes "unknown" (claude_seat_source_unknown), with a hint to pass--statusline-pathor
let the seat's wrapper refresh it. A seat whose supervisor entry gives it its own
CLAUDE_CONFIG_DIRis refreshed the same way.For Codex seats: before this, a seat without a Codex home of its own reported nothing, with
the reasoncodex_home_missing. Now it reads the shared Codex home, but only its own session
there, found by its thread id; a manual refresh uses only the thread the seat's wrapper saved.
It never shows another session's numbers; without a thread it says so
(codex_no_thread_yet). A Codex home, or its sessions folder, that is only a link to the
shared one counts as the shared one. One limit remains: separate Codex homes seeded from one
login show as separate accounts, although they share one budget.For everyone: each figure counts for 10 minutes from when it was seen. After that every
reader hides it, even when nobody rewrote the file:agenttalk capacity,agenttalk status
(which now showscapacity=current,capacity=stale(...)orcapacity=unknown(...)for each
seat), the web console andagenttalk attention. The next time the seat publishes a reading,
the expired figures are also removed from the file. A refusal flag expires with the window
it came from, and the latest verdict keeps the status and the window it named, so a refused
window is known even when its percentage reads low. Each reading
names the account it belongs to: the provider, the OS user and the folder the reading comes
from, the default folder too, so two user homes are never one account.agenttalk capacitylists the seats
that share an account under that account, each with its own reading and its age, newest
first; readings are never merged across seats. A seat's conversation fill is shown only when
it is known to be that seat's own. A manualagenttalk checkpoint savestill records the
status-line file's fill, as before this change, because a manual save cannot tell which
conversation it runs in; a save from Claude's own hook keeps it only when it names that
conversation. A fill older than 10 minutes is not recorded at all. A reading also says whether a window's length was reported
by the provider or filled in by agenttalk, and the file carries a version number. The
README's new section "Reading the capacity files" lists the fields other programs may rely on.What you need to do: nothing. The readings stay advice only: nothing waits for them or is
held back by them. To judge an account, read its newest seat's row. A wrapped Claude seat
usually shows no conversation fill: its own messages do not carry it, and the status-line
file's fill counts only when it names the seat's own session.Technical details:
src/agenttalk/capacity.py:claude_stream_reading,read_claude_stream,account_key,claude_account,
current_view(the read-time, per-part check every consumer uses) andfor_publication;read_localtakesstream=,now=,claude_home=,provider=,session_id=and
any_session_context=, and rejects a stream reading whosebindingdiffers from the
current account;_same_pathandaccount_keyresolve links first (os.path.realpath);account_key
always hashes the folder read,~/.claudeand~/.codexincluded;usable_epochaccepts a reset time only from 0 to the last second of year 9999, at
ingestion (stream, status line, Codex rollout) and in the readers (web._capacity_window,
cli._reset_in_minutes);current_viewdrops a saved refusal type that is not a window
name;detect_sourceis shared with the manual refresh;- numbers are parsed finite-only; the status-line read takes its time and content from the
same version of the file; - a thread's rollout is found by the name suffix
-<thread>.jsonlanywhere in the tree, or
by itssession_metaid (non-object records skipped), withCODEX_SHARED_SCAN_LIMIT4096
for the shared home; - new snapshot fields
primary_status,primary_window_basisandprimary_observed_at
(the same three forsecondary),last_status,last_status_at,last_status_window,
scope,accountand
schema_version= 2.
src/agenttalk/wrapper/session.py:SessionState.claude_rate_limit(with itsbinding),
folded inobserve_event; a failure there leaves no reading but keeps the binding; the
adapter's handling of a refused request is unchanged.src/agenttalk/wrapper/run.py:child_claude_config_dir, shared w...
agenttalk 0.98.0
In short: this release is mostly about the dashboards, and about seats that meet an
overloaded AI provider. The new dashboard (/v2) now works on a phone-sized screen, as one
column with tabs for what needs you, the team and the lead. Both dashboards stop treating
slightly old data as an error: the server now sends the data together with its age, and the
classic page keeps showing the last good data under an "Updating" banner instead of a red
"Degraded" box, asks for new data every 10 seconds instead of every 2, and gains a Refresh
live data button. An optional, read-only budget feed (--enable-budget, off by default) makes
this machine's gateway money figures available to the dashboard; there is no budget screen
yet. A Claude seat whose AI provider is overloaded, or whose usage limit cannot be confirmed,
now waits and tries again after 15 minutes, then 30, then every 60, instead of retrying every
few seconds for hours; this is on by default and can be switched off. The README now opens
with a plain-language front page, and several of its statements were corrected. The gateway
and its ledger are unchanged in this release, so upgrading needs no extra step.
Added
-
The new dashboard (
/v2) now works on a phone-sized screen. Until now the page had a fixed
minimum width of 1024 pixels, so on a phone it was cut off and had to be scrolled sideways.What you will notice: before this,
/v2on a narrow screen showed the desktop page, wider than
the screen. Now, under 1024 pixels, it is one column with a bar at the bottom to switch between
three parts: Needs you (the cards that wait for you, shown first), Team (usage windows
and the team list) and Lead (the lead's latest message, the chat and the message box). Every
button is at least 48 pixels tall, and nothing scrolls sideways down to 360 pixels wide. At 1024
pixels and wider the page looks and works exactly as before. Themes, the keyboard shortcuts and
the quiet, offline and needs-you states work at every width. The keyboard keysj,k,
Enterandlonly act on the cards of the Needs you part, so on a phone they do nothing while
Team or Lead is showing. A warning that the server cannot be reached, with its Retry button,
shows above every part, and the Needs you tab shows how many cards are open. There is no money (budget) part yet; it comes with its own feed later.What you need to do: nothing. This only changes how the page looks on a narrow screen; reaching
the dashboard from a phone is not part of this change (it still listens on this computer only).Technical details: one
@media (max-width: 1023px)block at the end of
src/agenttalk/web_static/console2.css; a static<nav id="c2-tabs">inrender_console2
(src/agenttalk/web.py);buildTabs/setTabinconsole2.jssetdata-c2-taband
data-c2-modeon#app. Tests:tests/console2_render.test.mjsand the phone tests in
tests/test_console2_web.py. -
An optional budget data feed for the dashboard. Before, the dashboard
server did not read this machine's gateway ledger. Startingdashboardor
servewith--enable-budgetnow makes those recorded money figures and
limits available atGET /api/budget, including the opening balance after
a reset and its month. The answer explains that it is not the provider's
bill and excludes other machines. The feed is off by default, reads without
changing the ledger, and reuses answers for ten seconds to limit short read
locks. There is no budget screen yet; existing dashboard answers are unchanged.
An incomplete ledger installation is reported as unavailable, rather than
mistaken for a machine that has never been set up.
Changed
-
The README now opens with a plain-language front page. Someone who has never
programmed can now learn from the first screen what agenttalk does, who it is for and
what they need first: an AI tool with working access to its model, Python, the
operating systems, and whether setup needs technical help. The front page then tells a
normal day with a small team and its honest limits, and ends with a short way in,
including how one lead sets up a supervised team. What agenttalk does well and under
which conditions, what stays on your machine and what agenttalk is not are now in the
first section of the guide. The detailed guide and reference follow further down, with
every fact kept; the list of optional features and the file locations moved into the
technical reference. A few points were corrected or added:- The bundled supervisor runs on Windows only (#356 tracks a monitor for Linux and
macOS). The project's tests run on Windows, Linux and macOS; the managed gateway's
background service uses Windows Task Scheduler or a systemd user service, so it
cannot be installed on macOS; and a wrapped Codex seat whose shell is bash or zsh
needs"reply_shell": "bash"in.agenttalk/supervisor.json. - You can start just one assistant, the lead, and have it set up a supervised team;
on Windows you then start the supervisor yourself (#355 would let the lead do that
too), and it starts the teammates in its settings in the background. - The pre-action check stops on a withdrawn (rescinded) request and, with
--gates,
on a gate at HOLD; the bundled lead instructions show it without--gatestoday
(#362). Sending a newer request in place of an old one does not stop the old one. - A bus command run without an agent name stops with "no agent identity"; only the
bundled skills fall back to a default name. The README used to say every command
fell back silently. - The wrapper's reply instructions leave out the seat's name and the wrapper does not
pass it on, so a supervised seat's reply can fail. An ordinary seat can carry its
name (AGENTTALK_SELF) in itssupervisor.jsonentry; a gateway-backed seat
refuses that entry and must reply with--from <seat>(#354, with the wider
problem in #178). - A restart tries to resume the assistant's session and starts a fresh one when it
cannot; accepted lessons reach a wrapped seat's turns (up to five) or a seat run by
hand throughagenttalk sync, as reminders; a work order closes on a done or
declined reply, on a verdict when the reply has no status field, by hand
(ack --to-request) or by withdrawal, so closed does not always mean completed. - No agenttalk command merges. The optional lanes can create a branch and a
worktree and, under their own checks, remove them;janitor --applycan save a
worktree's uncommitted changes as a commit on its branch. - Lanes need the bus folder inside the code repository (#245).
janitor --applycan follow a folder link in a rare case and delete files outside
the folder; use its report until that is fixed (#342).- Temp files are not yet routed into a seat's scratch folder (#336).
- The dashboard's views can still be slow on a large store with a cold cache (#251).
- The bundled supervisor runs on Windows only (#356 tracks a monitor for Linux and
-
A Claude seat whose AI provider is overloaded, or answers with an error that looks like a usage
limit but cannot be confirmed, now waits and tries again later, instead of retrying every few
seconds for hours. Until now such a failure was retried every 0.3 to 2 seconds until the
"100 attempts / 4 hours" rule gave up and dead-lettered the message. This is on by default,
and the same switch as the usage-limit park controls it.What changes: an overloaded provider (HTTP 529) gets two quick ordinary retries and then a
cool-down; a throttled one (a 429 without limit details, a status or window word the wrapper
does not know, or a rejection that no error result confirms) cools down at once. The seat then
tries again after 15 minutes, then after 30, then every 60. The message is kept, the seat stays
alive, and the wait and the tries made under it never count towards "100 attempts / 4 hours". A
restart does not make it try sooner: the saved time wins. Only structured proof from the seat's
own output counts, a later successful result cancels it, and message text never decides anything.
A proven usage limit is unchanged.What you will notice:
agenttalk statusflags the seatprovider_wait_parked(kind=...,retry=<time>);
attention,doctor,supervisorand both web consoles show it as parked in its own words
("waiting for an overloaded AI provider; tries again at ...", or "waiting on a possible usage
limit; ..."), never as a usage limit for an overload; the liaison gets one notice when it starts
and one when its kind changes. The seat's health saysprovider_wait_parked.A usage limit whose retry at the reset time was never used keeps that retry while a cool-down
interrupts it (a new record field,quota_wake_epoch, written only then): when the same limit
returns, the retry comes back if it is still ahead and is exactly the reset's own retry (a saved
time that does not match its reset is dropped, never used). The cool-down notice has the subject
"provider-wait park notice" and names only the saved next try.What to do: wait, or skip the message with
agenttalk ack --for <agent> --id <message id>(no
dead-letter record). Starting the seat again does not try sooner. To get the old behaviour for all
three kinds of park, setAGENTTALK_STOP_RETRIES_AT_LIMIT=0(orfalse,off,no); a message
that already carries a cool-down is then driven as before, and its attempts and time stay out of
its disposal counts.Known limits: Claude only; the first two overload retries are real attempts, so a message that
already has 19 eligible attempts reaches the 20-attempt escalation with the first, and one with 98
attempts and four eligible hours reaches the disposal with the second (the promise of no disposal
starts with the cool-down); the 529 and plain-429 cases in the tests are made up, because no real
sampl...
agenttalk 0.97.0
In short: this release is about seats that run into limits, and about a safe way
for other programs to read the gateway's money figures. A Claude seat that runs out of
its 5-hour or weekly allowance now stops and waits, instead of retrying for hours and
then losing the message, and it keeps its working context while it waits. A seat's
health now names the real cause of a failure, for example a usage limit and its
window; it no longer says "rate limited" just because an error contains the letters
"rate", and it never guesses when a seat will recover. For a program that keeps its
own accounts, the gateway gains a read-only gateway report, each receipt now names
its month, gateway receipts works from any folder, and the Qwen gateway can tie a
paid child turn to an outside quota reference and keep a receipt of what it spent. An
optional turn journal can record what each turn did. A refused work order no longer
prints anything that looks like proof it was sent, and the new console no longer hides
a stalled seat the server had already flagged. Tests no longer reach a running gateway
by default, CI logs list every skipped test with its reason, and two rare test
failures are gone or explained. Upgrading a running gateway is a separate step: the
ledger change for quota references is opt-in (agenttalk gateway binding-install),
and older agenttalk versions refuse a ledger once it is migrated, so read the gateway
entries below before you upgrade one.
Changed
-
A Claude seat that runs out of its allowance now stops and waits, instead of retrying for
hours and then losing the message. Until now, when a wrapped Claude seat used up its 5-hour or
weekly allowance, the wrapper started the model again every few seconds for four hours (844 and
809 tries in two real cases) and then dead-lettered the message. This is on by default.What changes: the first time the seat proves it is out of allowance (Claude reports a rejected
usage event and ends the turn in error), the wrapper parks the message. It tries once more
each time the wrapper is started again, and once 30 seconds after the reset time Claude states
(only when that time is in the future and within 8 days). Everything else behaves as before.What you will notice: a seat that stops and waits.
agenttalk status,attention,doctorand
both web consoles show it as parked on a usage limit ("until " or "until restarted"), and
the liaison gets one notice. The seat stays alive and the supervisor leaves it alone. The
message is kept, but messages behind it wait, includingreleaseandend.What to do: wait for the stated time, or start the seat again now with
agenttalk request-restart --for <agent>(a protected seat also needs--force-protectedand
--acknowledge-live-protected-kill), or skip the message with
agenttalk ack --for <agent> --id <message id>(no dead-letter record). To get the old behaviour
back, setAGENTTALK_STOP_RETRIES_AT_LIMIT=0(orfalse,off,no) in the wrapper's
environment; it gives the previous behaviour. One qualification: a message that already carries
a park when you switch it off is driven as before, but the attempts and the time it spent parked
stay out of its disposal counts.With the optional turn journal on, the turn that proved the limit is one failed dispatch (the same
failure class as with the switch off), nothing more is recorded while the seat waits, and a later
successful try gives a new dispatch and exactly onecompletedfor the message. A parked seat is
held to the same rule as a stalled warning in the web console: always counted as needing attention,
never "All quiet" or "not for you", and no saved "Later" choice hides it.Technical detail: a new
usage_limitfailure word, new fields in the message's attempt record
(park_state,parked_at,parked_generation,park_count,probe_marker,
excluded_attempts,parked_seconds_total,limit_failures,limit_window,reset_epoch,
wake_epoch,last_reset_epoch,probed_wake_epoch,notice_key,notice_routed,
notice_tries,notice_next_at; added only, none renamed or removed), a marker file
state/usage-limit-park/<agent>.json, the health reasonusage_limit_parked, and a
usage_limit_parkfield instatus --json, the supervisor report and the web state rows. It
replaces the approach of pull request #104 (never merged), which read the provider's error text.Fix round 1 (this update): a cold read found a few edge cases the first version did not
handle cleanly, all now fixed:- A momentary file-system hiccup while refreshing the marker could, on some Python versions,
escape and stop the wrapper's own heartbeat - the seat would then look dead until restarted.
The marker refresh is now one single protected step, start to finish. - A damaged or very unusual marker file could carry a time so large or so early that showing it
broke the very screen trying to show it (status,doctor, or either web console). Every
time in the marker is now checked against what any of those can actually display; a field
that cannot be shown is simply left out, never crashes the screen, and the rest of the marker
still reads normally. A file missing one of its eleven documented fields is now refused
outright, as the documented contract always said it should be. - The "how long has this seat been parked" shown in
attentioncould read as a few seconds
even after days, because it was reusing the marker's own refresh time by mistake; it now
comes from when the park actually began. - The one liaison notice for a park no longer shows twice (once in the main list, once as its
own separate question that never went away on its own once the park ended) - it is shown
once, as a single live warning, like a stalled seat already is. - A notice meant for the liaison no longer silently fails to send when the parked seat is
itself the liaison and a separate lead exists to receive it instead. - One unrelated file left in an internal folder could previously stop
doctorfrom listing any
parked seat at all; it is now skipped on its own.
What you will notice: nothing new to do - these were all edge cases that could otherwise have
hidden a real park or looked like an unrelated crash.Fix round 2: a further read found that round 1's notice fix only hid the duplicate card,
without closing the obligation it left behind, and opened a second gap of its own; three
further edge cases in the park's own bookkeeping were also found. All now fixed:- A seat whose park had already recovered could still leave the liaison with an unanswered
question showing in places that track what the liaison still owes a reply to - round 1 only
hid the duplicate card, it never closed the question itself. The liaison notice is now
purely informational everywhere, the same as any other status update: it was never a
question owed a reply to begin with, so it can never stay stuck looking like one. - Publishing the small status file that adds a park's reset time and freshness can fail
without the park itself being affected - round 1's fix for the point above could then hide
the only warning a parked seat had. The warning itself no longer depends on that file: it
shows (without the reset-time detail) whenever the seat's own durable record says it is
parked, file or no file. - A damaged or hand-edited internal count could, in rare cases, cause a message to be
dead-lettered after only one real try, even with this whole feature turned off. Both
counts behind that decision are now kept sane before they are used. - A status file with a date but no time zone was read as local time instead of being
rejected, which could make a park look a different age on two different machines. A date
with no time zone is now refused, same as any other damaged field. - The new console's "needs you" panel showed a seat that had just started up the same as one
that was confirmed stuck or dead. A normal startup now reads as itself, not as a failure;
a genuinely stuck or dead seat is unaffected. - Round 1's fix for a notice going to the wrong place also changed where two OTHER, older
kinds of notice go when this whole feature is switched off. Narrowed to affect only this
feature's own notice; the other two are back to their original behaviour.
What you will notice: nothing new to do - these were all edge cases in the park's own
bookkeeping, surfaced only by a damaged file, a missing optional file, or an unusual sequence
of events.Fix round 3 (park reader recast, this update, the last): round 2's fallback for a missing
status file was added to only one of the seven screens that show a park (attention); a
further read found it could also show a stopped wrapper as freshly parked instead of "not
responding", and could show an earlier, already-handled message's park instead of a new one.
Every screen now reads one single, shared answer instead of each finding its own way to cope
with a missing or outdated status file:status,doctor, the supervisor report, the web seat row and web attention all now show
a park exactly the same wayattentionalready did - built from the seat's own durable
record whenever the status file is not readable, not only inattention. Three of those
five previously showed nothing at all in that case.- A park is now always the CURRENT message waiting for that seat, found the same way the
wrapper itself finds its next message - never an older, already-handled one the status file
happened to still mention, and never silently missing a second park that started after the
first was handled. - A seat whose wrapper has actually stopped no longer reads as freshly parked just because its
durable record still...
- A momentary file-system hiccup while refreshing the marker could, on some Python versions,
v0.96.0 - one plain voice for people, a lead routine, and a clearer "what needs you" panel
What is in agenttalk 0.96.0
agenttalk is a tool that lets AI coding agents from different companies work together as one team: they send each other work, reviews and answers through a shared message store, and a lead agent coordinates them. This release is mostly about being clear to people: what the agents write, what the lead does every half hour, and what the "what needs you" panel shows.
The main things in this release, each explained below:
- One plain-language voice for everything a person reads.
- Leads get a written routine: a regular check-in and a handover note.
- A clearer "what needs you" panel.
- Answered tasks stop looking unfinished.
- Right after an upgrade, the lead can send work at once.
- The out-of-date PDF manual is gone, and slow automatic checks on Windows get more time.
If you already have agenttalk installed: refresh the skills, or the new writing and lead guidance will not arrive. Preview with agenttalk install-skills --dry-run --force, back up any local edits you want to keep, then run agenttalk install-skills --force. A fresh install needs only agenttalk install-skills.
One plain-language voice for everything a person reads
What changed: the agents already explained changes in plain words in release notes and pull requests. Now one shared guide covers everything a person reads: documentation, code comments and the text on screen. Each kind has its own length and shape. Documents open with a short "In plain words" summary; comments say why in a sentence or two; on-screen text is short, says what you can do next and never blames you. Messages between agents stay short and exact, because only agents read them.
What you will notice: new and changed documents start with a plain summary, and new comments and on-screen text read more plainly. The README and the new-user manual already open this way, and the new console's labels, buttons and messages were rewritten in plain words. Existing documents are not rewritten just to change their voice.
Leads get a written routine
What changed: the lead skills now describe a regular check-in (for example every 30 minutes: new messages, which agents are alive or stuck, open reviews, budgets, free memory, knowledge, spend) and a short handover note (for example every two hours and before any reset) so that a restarted lead can carry on. They also say what to report to the person in charge: only decisions, actions that need them, and money alarms.
What you will notice: a lead that loads the updated skill keeps a steady rhythm and leaves a handover note.
A clearer "what needs you" panel
What changed:
- A supervisor warning about a stuck process now says whether the supervisor itself is running, not running, or unknown. This is a plain fact, never a reason to treat the warning as less urgent.
- A pile of old failed messages (7 days or more) from one agent is folded into one row with the exact count and the commands to reach each of them. Nothing is hidden or left uncounted, and the count at the top always includes everything.
- When the server is briefly busy, the panel waits and tries again instead of showing an error at once. A real failure still shows after a few tries.
Answered tasks stop looking unfinished
What changed: a reply that gave a verdict without a separate "done" status used to leave its task listed as open. Such replies now count as answers, including older ones. An explicit "in progress" status still keeps a task open, and a reply with neither warns how to close it.
What you will notice: the list of open tasks shrinks to the ones that really are open. No clean-up command is needed.
Right after an upgrade, the lead can send work at once
What changed: sending a task used to be refused while any agent in the team ran an older version than the sender. Now only the agent that receives the task is checked, against the first version that understood tasks (0.88.0).
What you will notice: after an upgrade the lead can send work to any agent on 0.88.0 or newer straight away, without waiting for the whole team to restart.
Smaller changes
- The PDF copy of the new-user manual is gone. It was made for version 0.74.0 and had fallen about twenty versions behind. Read
docs/AGENTTALK-NEW-USER-MANUAL.mdinstead. - Slow automatic checks on Windows get more time, and a time-out while scanning a project's Git sub-modules no longer crashes the scan.
- Four rules in the plain-language guide no longer pull in different directions.
The full list, with technical details for each change, is in CHANGELOG.md.
Install: python -m pip install "git+https://github.com/zoolok17/agenttalk.git@v0.96.0"