Repository navigation
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), and returns
without consuming or reordering the head. A later loop that reaches an honoured release consumes it without
exiting. Covers both drives and a new wrapper generation that meets the same parked head (it stands down
before the one re-probe). -
A background agent now starts from a normal virtual environment on Linux and macOS (#493).
The wrapper looked up its own Python by following the environment's link to the system Python, which
does not have agenttalk installed, so it refused to start.What you will notice: if you install agenttalk into a standard virtual environment (
python3 -m venv)
on Linux or macOS,agenttalk wrapnow starts the agent instead of stopping with "No module named
agenttalk". The agent's ownagenttalkcommands use the same environment. Windows is unchanged.What you need to do: nothing. If you worked around this with
python3 -m venv --copies, you can go
back to a normal environment.Technical details:
_agenttalk_py()and the owed-action dispatch pin (_pinned_executable) now use the
interpreter path as the process was started (made absolute, not resolved through links) via the new
interpreter_path.launch_path. Windows keeps the resolved path. The dispatch pin still checks that the
target is a regular file. The supervisor, the comprehension worker and the doctor fallback already pass
sys.executableunresolved. The gateway service identity (ovh_gateway_service, used for the scheduled
task and the systemd unit) still resolves its executable; that is unchanged here.