Repository navigation
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 it would most likely
fail, and a cheap way to test it. The lists are merged, and someone who wrote neither marks each
idea adopt, reject or already in the plan, with one line on why. A short quick start at the top
of the skill covers just these steps.What is in it: thirteen games, for example "forbid the favourite" (plan without the obvious
answer, then bring it back), "pull one assumption" and "evidence from the future" (write the
support ticket from a future where the idea works). Twelve roleplay cards give a viewpoint to
think from, such as an attacker, an auditor, the on-call engineer woken at night or the person
who will make the decision. Five formats are for pairs or groups, such as a courtroom or a red
team against a blue team. In a team round, each pair or group picks a different game and works
alone before they compare.The safety rules: what a roleplay card claims is a guess to be tested, never a fact. Tests and
probes run only on copies or test environments, never on live systems or anyone else's. A
simulated decision-maker is labelled as simulated, never speaks in the real person's name, never
replaces asking them, and never hides an option from them. "Nothing useful" is an accepted
result, a game never decides what is in scope, and whether to do the work at all stays with the
challenge skill.Each round leaves a one-line score of what was adopted and which game or roleplay card it came
from. A card is judged only after at least five plays; one that never added a useful idea that
only it found can then be reworked or dropped. An honest note: the evidence is small. One blind
trial of three runs tried three of the games. The game list was never judged better than the
ordinary list, and once worse. The gain came from merging two independent lists, each of which
added useful ideas the other missed, and judging the lists took more agent time than playing
the game. The roleplay cards, the formats, the team round and the other ten games are untried. That a
game makes the second list more different than a second ordinary list would is a hope the scores
will test, not a finding.What you will notice: nothing changes on its own. Agents are meant to use the skill only at those
moments, and it is meant to be named in a lead's work order (the written task a team lead gives
an agent).What you need to do: run
agenttalk install-skillsto install it.Technical details:
src/agenttalk/skills/devkit/thinking-games/SKILL.md(categoryproduction,
planning-artifactevidence). It is listed in the shared routing index, section 3.2 of
docs/ROLES-SKILLS-PROCEDURES.md, the user manual's skill table and the devkit list in
tests/test_install_skills.py. -
A migration playbook, and the lessons behind it, now ship with agenttalk. Everything the
maintainers' teams learned from their own migrations (Python 2 to 3, Django, PHP and Laravel, Java
and Spring, Docker and Kubernetes, payment code) used to live only in their own lesson stores,
so a new user started with none of it.What you will notice: a new guide,
docs/MIGRATION-PLAYBOOK.md, for a team that moves a
codebase to a newer framework, language version or platform and must show that it still behaves
the same. It has seven stages (assess, baseline, one step at a time, prove, concurrency and data,
packaging and runtime, review and hand-over). Each rule names the stack it applies to, when it
applies, why, and one check you can run. It starts with the twelve rules to apply first, and
keeps general practice that was not measured in these runs in its own marked section. The same
124 lessons are insrc/agenttalk/knowledge_packs/migration.jsonl, one per line, for tools that
load them into a team's lesson store;agenttalk knowledge pack load migrationloads them into an existing store (see the lesson-pack entry above).
Many rules rest on a single case, and the guide says so.What you need to do: nothing. Read the guide before a migration.
Technical details: the pack lines carry
key,scope,trigger,body,applies_to(with exactly
onestage-*tag),evidence,packandpack_version; keys are bare slugs.
tests/test_migration_pack.pychecks the format and that the guide and the pack stay in step. The
guide ships in the source package.
Fixed
-
A background Claude agent that cannot find
claudenow gets advice about Claude, not about Codex
(#508, item 1). Before an agent's first turn, its wrapper (the program that runs the agent in the
background) checks that it can start the agent's AI tool. When it could not, it always gave the same
advice: "set AGENTTALK_CODEX to the native codex.exe". A Claude agent on Linux was told how to fix a
Codex install on Windows.What you will notice: before this, every agent got the Codex advice. Now the advice names the agent's
own tool and fits the computer it runs on. A Claude agent is told to give the full path ofclaude
after--, with the usual place as an example (~/.local/bin/claudeon Linux and macOS,
C:\Users\<you>\.local\bin\claude.exeon Windows) and the command that prints it (command -v claude,
orwhere.exe claudeon Windows, which works in both PowerShell and the Command Prompt). A Codex agent is still told aboutAGENTTALK_CODEX, and "native
codex.exe" appears only on Windows. The same applies when the path points at a Windows helper script
(.cmd,.bator.ps1) that the wrapper cannot start directly.What you need to do: nothing.
Technical details: new
wrapper/run.py_launch_cli_remediation(cli, is_windows=...), used by both
refusals inpreflight_launch_runtime(executable not found, and a shim).preflight_launch_runtime
takes an optionalis_windows(default: the running system). Any other--clivalue gets "pass the
full path of the executable after --". Tests intests/test_wrapper_loop.py:
test_launch_preflight_missing_claude_gives_claude_advice_not_codex,
test_launch_preflight_missing_codex_gives_codex_advice_not_claude,
test_launch_preflight_missing_cli_advice_fits_the_platform(four cases) and
test_launch_preflight_claude_shim_gives_no_codex_advice. -
When an agent cannot start and no supervisor is running, the notice now says how to start it again
(#508, item 2). When an agent's wrapper cannot start the agent's AI tool, it sends a notice to the
person or agent who looks after the team. The notice ended with "run: agenttalk request-restart". That
command only asks the supervisor (the background program that starts and restarts agents) to restart
the agent; with no supervisor running, nothing happens.What you will notice: before this, the notice always said to run
agenttalk request-restart. Now it
says that only when a supervisor is running. Otherwise it says that no supervisor is running, so
request-restartwould do nothing: fix the launch command as the advice in the notice says, then start
the agent again the way it was started (for example with the sameagenttalk wrapcommand).What you need to do: nothing.
Technical details: new
cli._supervisor_running(store): a valid supervisor instance marker
(Store.read_supervisor_instance) whose owner process is not confirmed gone (_owner_identity_gone).
When the owner's liveness cannot be checked, the supervisor counts as running and the old advice stays.
Used by_launch_config_blocked_notifier. The notice for an agent parked on a message ("wrapper
config-blocked") still saysrequest-restart; it is not part of this change. Tests in
tests/test_wrapper_loop.py:test_cmd_wrap_launch_blocked_without_supervisor_says_start_again,
test_cmd_wrap_launch_blocked_with_dead_supervisor_says_start_againand
test_cmd_wrap_launch_blocked_with_live_supervisor_keeps_request_restart. -
A work order sent to an agent that has never started now says so, instead of blaming an old
version (#508, item 3).agenttalk taskrefuses to send a work order to an agent whose agenttalk
version is too old to read one, because that agent would quietly drop it. An agent that had never
started has no version on record, so it was refused as if it ran an old version, with "(unknown)"
as its version.What you will notice: before this, a work order to a new agent that had not run yet was refused
with "the recipient is on an agenttalk build that predates task-kind support ... (unknown)". Now,
when the agent has no heartbeat (the "I am alive" stamp an agent writes while it runs) and no
health record at all, the refusal says the agent has not started yet, so agenttalk cannot tell
whether its version can read a work order. It says to start the agent first, or to send with
--force: then the order waits in the agent's queue and is read when the agent starts, if it runs
agenttalk 0.88 or later. With--forcethe notice says the same. An agent that has run but never
reported its version is still refused as "(unknown)", as before. The guide for leads
(docs/LEAD-SETUP-BRIEF.md, "Known rough edges") quotes the new message.What you need to do: nothing. Start the agent, then send the work order again.
Technical details: new
cli._never_started(store, agent):Store.read_heartbeatisNoneand
the health file (Store.health_path) does not exist.cmd_taskuses it for the refusal and the
--forcenotice._recipients_behind_kindandagenttalk broadcast --kind taskare unchanged.
Tests intests/test_cli.py:test_task_to_a_seat_that_never_started_says_so_not_old_build,
test_task_force_to_a_seat_that_never_started_says_when_it_arrivesand
test_task_to_a_seat_with_only_a_heartbeat_still_reports_unknown_build. -
agenttalk knowledge search --tags <tag>now works without a search word (#508, item 5). A
lesson in the team's knowledge store carries a few short tags (for exampleshell), so it can be
found again later. Searching by tag alone failed, because the search always demanded a word as
well.What you will notice: before this,
knowledge search --tags shellstopped with "the following
arguments are required: query". Now it lists every lesson taggedshell; add a word to narrow the
list. A search with neither a word nor--tagsstill stops, and now says how to search by tag. The
guide for leads (docs/LEAD-SETUP-BRIEF.md) no longer says a word is needed.What you need to do: nothing.
Technical details: the
queryargument ofknowledge searchis optional (nargs="?");cmd_knowledge
refuses a search with no query and no--tags(exit 2). An empty query ("") still matches every
note, as before.knowledge.select_knowledge_viewalready supported no query, so the stored notes
and the selection are unchanged. We made the tag-only search work rather than only improving the
error, because it needed no new stored field or command. Tests intests/test_knowledge.py:
test_search_by_tag_alone_needs_no_search_wordand
test_search_without_a_word_or_tags_says_how_to_search_by_tag. -
agenttalk knowledge publishnow reports three more kinds of problem in the same refusal as the
others (#513). Saving a lesson or a note to the team's knowledge store takes several options. Most problems were already
listed together, but three kinds came separately, so a new user had to run the command again for
each one: a missing--keyor-m, a--scopethat is not one of the allowed words, and a domain
(the part of the project a note belongs to) that the team's domain list does not accept, such as
processfor a note that is not a lesson.What you will notice: before this, a missing
-mor an unknown--scopestopped the command before
anything else was checked, and a refused domain was reported only after every other option was
right. Now these three are listed together with the problems that were already grouped, one per
line. Some refusals still come on their own:- The command-line reader stops first, and alone, at a missing or unknown
--type(it decides which
other options are needed), at an unknown--anchor-kindvalue, and at an option it does not know. - A
--verified-againstthat does not name a commit, or a key that already holds a note of another
type, is reported only once everything else is right.
Nothing is saved while any problem is listed.
What you need to do: nothing.
Technical details:
--keyand-mare no longerrequired=in the parser, and--scopeon
knowledge publishno longer uses argparsechoices(the help still lists the allowed words);
_kn_publish_preflightchecks all three (kn.LESSON_SCOPES). When the preflight finds problems and
a domain applies (--domaingiven, or a lesson),cmd_knowledgealso runs
_knowledge_resolve_domain_for_publishon a fresh read ofdomains.jsonand adds its error (an
unreadable or invaliddomains.jsonis listed too). This relaxes an earlier rule, "all field errors
before any registry, Git or ledger I/O": the read-only registry read may now happen on the error path; Git and the ledger are still untouched, and the binding check
still runs under the lock. Tests intests/test_knowledge.py:
test_publish_lists_missing_key_message_scope_and_dates_in_one_refusal,
test_publish_names_a_refused_domain_with_the_other_problems,
test_publish_lists_a_broken_registry_with_the_field_errors, and the renamed
test_publish_preflight_reports_all_errors_before_git_or_ledger_io. - The command-line reader stops first, and alone, at a missing or unknown
-
agenttalk knowledge publishnow says which domain it stored the note in (#508, item 6). Every
lesson has a scope (what kind of lesson it is, for exampleops) and is stored in a domain (the
part of the project it belongs to; lessons go toprocessunless you give--domain). The two are
easy to mix up. A lesson published with--scope opsis stored in domainprocess, so the next
command, for exampleknowledge curate verify --domain ops, found nothing.What you will notice: before this,
publishprinted onlypublished note <id> process/<key>, and
the help did not say that--scopeleaves the domain alone. Now a second line says
stored in domain process, adds "(--scope ops labels the lesson; it does not choose the domain)"
when the two differ, and gives the command to verify the note with the right domain. The help for
--scopeand--domainsays the same. What is stored has not changed.What you need to do: nothing. Use the domain that
publishprints in the next command.Technical details:
cmd_knowledge(publish) prints the extra line after the unchanged first line;
the--scopeand--domainhelp texts ofknowledge publishchanged. Tests in
tests/test_knowledge.py:test_publish_output_names_the_domain_a_lesson_was_stored_in,
test_publish_output_for_a_note_names_its_domain_without_a_scope_hintand
test_publish_help_says_scope_does_not_choose_the_domain. -
The operations guide now explains what to do when an agent looks stuck (#497). Two causes were
not written down anywhere an operator would look.What you will notice:
docs/OPERATIONS.mdhas a new section, "An agent looks stuck", and a row
for it in "If something is wrong, start here". It says two things. First, after you update Claude
Code or Codex, restart the agents that run underagenttalk wrap: each one finds its tool's file
once, when it starts, and an update can replace or remove that file. Second, an agent that shows
"working" for far longer than a turn usually takes may have a hung tool rather than a busy one. The
guide says which case the wrapper already ends by itself on Linux and Windows: a Codex agent under
wrap --loop, after 30 minutes with a program it started alive for 10, by default. It also says
plainly that on macOS this watchdog never ends a turn today. Everywhere else the operator watches the
agent's log and restarts the agent by hand. The guide notes that a quiet log alone does not prove
a hang.What you need to do: nothing. No program behaviour changed; spotting a hung tool automatically, and
making the watchdog work on macOS, are not part of this change.Technical details: documentation only (
docs/OPERATIONS.md). The watchdog facts come from
wrapper/turn_watchdog.py:TurnWatchdogConfigdefaults to 1800 s and 600 s, and is on by default
only for a continuouswrap --loop --cli codex(seecmd_wrap). The process list comes from
_snapshot_posix(ps -axo pid=,ppid=,etimes=,comm=) or_snapshot_windows(the PowerShell
recorded bysupervise --select-pwsh). Apple'spshasetimebut noetimes, so on macOS the list is never available. The
watchdog then does nothing, by design: it never kills without a list.