agent-zero¶
Agent Zero (catalog agent agent-zero) is agent0ai's open-source Python agent, usually run in a
Docker container whose install directory is /a0; it is driven from its web UI, from messaging
plugins (Telegram, WhatsApp, email), from editors through ACP (the Agent Client Protocol) and from
the host-side A0 CLI connector. Three companions put its data on the host: the A0 Install scripts,
the A0 Launcher (an Electron app that manages instances) and the A0 CLI connector (a host-side
client). Its Orchestrator plugin can drive other coding CLIs, Hermes among them. One JSON file per
chat holds two parallel records of the conversation: the UI log (timestamped, truncated, last 1000
items) and each agent's LLM history (full text, no timestamps, compressed over time). Parsed: the
agent-zero parser reads chat.json, its messages/ files and the legacy per-chat JSON, and beside
them the scheduler's task list, the Telegram chat map, the tool policies, the Orchestrator's
settings, two plugin switches and two keys of the connector's .env.
Source and evidence¶
agent0ai/agent-zero at commit
e3051fb584b1a36be2b0a0c90606f1c2c2d356ec.
The LICENSE file at that commit is plain MIT
(LICENSE:1-4),
not a custom licence. Python, source public. Three companion repositories decide where the data
lands on the host and were also read: agent0ai/a0-install
at
c89b4026e9f16f53389e75537783411fefdd53f1
(installer scripts), agent0ai/a0-launcher at
b0333d80b5abf38d8481f55b667b0cf23d805bbb
(Electron launcher, MIT,
LICENSE:1),
and agent0ai/a0-connector at
76e834f20e50f6e47954c89ee39dd4c5b50d81b7
(the host-side "A0 CLI", MIT,
LICENSE:1).
All claims are from source or the in-repo docs, read only, not run.
Observed¶
- No real install: nothing was installed or run.
- The Docker volume layout of chats (
chats/<ctxid>/chat.jsonat the volume base, Transcript stores) is not observed on any real install, source-derived. - The
session synced:andsession relayed:rows are fixture only (Sync, relay and origin).
Source reviews¶
- 2026-10-21: agent0ai/agent-zero at
ff2a5b9and agent0ai/a0-connector at3741c88, as reviewed on 2026-10-19: the proposed permission, model, past-use, deletion, scratch and origin rows became parser rows, the scheduler's file shape, the OAuth provider tokens, the model override's API key and the source-host statement were added, and the collector lines for the WhatsApp session, the ACP workspaces and the connector's Windows screen captures are recorded. - 2026-10-19: agent0ai/agent-zero at
ff2a5b9(committed 2026-10-13), againste3051fbcited above; a0-install unchanged, HEAD is stillc89b402; a0-launcher ata69403dagainstb0333d8; agent0ai/a0-connector at3741c88against76e834f. The review added the permission records, the per-chat model override, the editor-session keys and the host path they record, the records of past use and what a delete leaves, the WhatsApp login state, the launcher's own WSL distribution and the connector's screenshots, and recorded the small format drift in Format versions.
Collection¶
Per-user storage¶
Agent Zero itself never resolves a home directory. Every path is relative to the install directory,
the parent of helpers/
(helpers/files.py:23,575-584),
shown to the agent as /a0/...
(files.py:618-623).
In the container that is /a0; all user state is under /a0/usr and /a0/tmp, both gitignored
(.gitignore:26-39).
Where that lands on the host depends on how it was started:
| Deployment | Host location of /a0/usr |
|---|---|
A0 Install (install.sh, install.ps1) |
~/agent-zero/<container-name>/usr, override --data-dir (install.sh:1630,1650-1652,1830; install.ps1:30,1856,1874) |
| A0 Launcher, default "host directory" mode | ~/agent-zero/<instance>[-N]/usr (state_store.js:144-149, index.js:890-899) |
| A0 Launcher, "named volume" mode | Docker volume a0-launcher-<slug>-usr (index.js:948-951) |
README docker run |
Docker volume a0_usr (README.md:92) |
docker/run/docker-compose.yml |
./agent-zero beside the compose file, mounted as all of /a0 (docker-compose.yml:5-6) |
| Native ("development") run | the git clone, anywhere; the docs example is ~/Desktop/agent-zero (docs/setup/dev-setup.md:34-37); native means not --dockerized (helpers/runtime.py:59-64) |
Named volumes live under the Docker data root (or inside the Docker Desktop
VM), outside any home, and are not reachable by a home-relative catalog;
since collector 1.5.0 the DOCKER_VOLUMES table collects *a0_usr and
a0-launcher-*-usr volumes with usr-relative exclusions and secret globs. Only
the native run has usr/ and tmp/ beside the source, a .venv or
.conda, and a legacy root .env.
Scratch directories¶
usr/workdir is the working directory of a chat with no project
(helpers/settings.py:604),
and usr/projects/<name> directories, clones included, belong to the agent's own tree; both are
collected under the agent-zero entries and the volumes. Chats name them by container path
(/a0/usr/...), which the analyzer's catalog rule cannot match to a home path. An editor session
on the container transport can name its own working directory inside the container
(Editor sessions). The connector's screenshot directory
(Host-side companions) is the one scratch location outside usr/; it is
collected only on Windows, where the system temp directory is inside the home.
Contents of usr/¶
chats/<ctxid>/chat.json, one per chat or scheduled-task context, andchats/<ctxid>/messages/<n>.txtfor tool results of 500 characters or more (helpers/persist_chat.py:17-19,47-48,extensions/python/hist_add_tool_result/_90_save_tool_call_file.py:23-40).settings.json(helpers/settings.py:182),.env(helpers/dotenv.py:17-18),secrets.env(helpers/secrets.py:19).memory/<subdir>/: LangChain FAISS store,index.faiss,index.pkl(pickled docstore holding the memory text),embedding.json,knowledge_import.json(plugins/_memory/helpers/memory.py:180,197,269,550,666-673).knowledge/user knowledge files (memory.py:676-689).projects/<name>/with metadata in.a0proj/:project.json,mcp_servers.json,instructions/,knowledge/,skills/,memory/,secrets.env,variables.env(helpers/projects.py:11-17,77-86,672-684;secrets.py:554).workdir/, the agent's default working directory (settings.py:597).scheduler/tasks.json, or sinceff2a5b9scheduler/tasks.yamlwhen only the YAML file exists (helpers/task_scheduler.py:512-515;helpers/task_scheduler.py:29,521).agents/,skills/,plugins/user extensions (helpers/subagents.py:12,helpers/skills.py:91).uploads/,upload/,downloads/,email/(helpers/migration.py:24-31)..time_travel/workspaces/: shadow git history ofusrworkspaces (plugins/_time_travel/helpers/time_travel.py:23-24).
Older releases kept chats, scheduler, uploads, settings and secrets under tmp/, memory under
memory/ and the .env at the install root; startup moves them into usr/
(migration.py:24-38,95-107),
so an image of an un-upgraded install may hold them in the old places.
Also under usr/, cited at ff2a5b9:
- Tool policies, the per-profile and per-project permission lists:
usr/agents/<profile>/plugins/_tool_access/config.json,usr/projects/<name>/.a0proj/plugins/_tool_access/config.jsonand.a0proj/agents/<profile>/plugins/_tool_access/config.json(plugins/_tool_access/README.md:4-9; Permission rows). - Plugin switches: an empty
.toggle-0(disabled) or.toggle-1(enabled) in a plugin's directory underusr/plugins/(helpers/plugins.py:60-61). plugins/_model_config/presets.yaml, the model presets a chat can select (plugins/_model_config/helpers/model_config.py:10,99-101).email/state.jsonandemail/attachments/of the email plugin (plugins/_email_integration/helpers/handler.py:38-39),whatsapp/media/and, under the install'stmp/,whatsapp/media/andwhatsapp/session/of the WhatsApp bridge (plugins/_whatsapp_integration/helpers/handler.py:31,plugins/_whatsapp_integration/helpers/storage_paths.py:6-11); the session directory is the bridge's login state (Credentials).tmp/is besideusr/only in a native run or a whole-/a0mount; the installer, the launcher and the README volume mountusralone, sotmp/stays inside the container.
Host-side companions¶
These are home-relative:
- A0 CLI connector:
~/.agent-zero/.env(instance URL, last chat id and host, remote-exec and computer-use flags; since the connector's3741c88_ENV_DIRis atconfig.py:10-12) and~/.agent-zero/session_cookies.json(a0-connector config.py:8-10,15-25), same path on every OS. Its managed browser profiles are under~/.local/share/a0/browser-profiles,~/Library/Application Support/A0/Browser Profilesor%LOCALAPPDATA%\A0\Browser Profiles(host_browser_common.py:476-487). - A0 Launcher: Electron
productName"Agent Zero Launcher" (package.json:51), souserDatais the Electron default directory of that name; it holdsdocker_manager/state.jsonanddocker_manager/cache(state_store.js:13-23). The launcher's Windows installer treats%APPDATA%\a0-launcher(the package name, not the product name) as the launcher's settings directory and keeps it across a reinstall, renaming it toa0-launcher-installer-backupwhile it runs (packaging/platforms/windows/installer.nsh:55-62); which of the two names Electron uses at run time was not resolved from source. - A0 Launcher on Windows, since
a69403d: on a host without Docker Desktop the launcher's setup can import its own WSL distribution namedUbuntu, with its own Docker engine, intoAppData/Local/agent-zero/wsl/Ubuntu(shell/docker_adapter/impl/WindowsWslRuntime.mjs:23,31,353), whose virtual disk holds the Docker engine and the container data and is kept on uninstall (docs/runtime-troubleshooting.md:38-43). A named volume of that engine is inside the virtual disk, out of reach of the collector's volume walk; no catalog line names the directory, and Agents outside dot directories incollectors/docs/coverage.mdgives it as a manual step. - A0 CLI connector, computer use: each screen capture the connector takes for the agent is written
to
<system temp>/_a0_connector/computer_use/<ctxid>/<uuid>.pngand older captures are deleted as new ones arrive (computer_use.py:242-247,1329-1340,1348-1356), overridable withA0_COMPUTER_USE_HOST_ARTIFACT_ROOT(33). The system temp directory is/tmpor$TMPDIRon Linux and macOS, outside the home, andAppData/Local/Tempon Windows, inside it; the catalog lineagent-zero|AppData/Local/Temp/_a0_connectorcollects the Windows form, and the other two are a manual step in Agents outside dot directories incollectors/docs/coverage.md.
Credentials¶
usr/.env: provider keys asAPI_KEY_<PROVIDER>,AUTH_LOGIN,AUTH_PASSWORD,RFC_PASSWORD,ROOT_PASSWORD; settings strip these before writingsettings.json(settings.py:540-570).usr/secrets.envandusr/projects/*/.a0proj/secrets.env: user secrets the agent references as§§secret(KEY)(secrets.py:17-19,535-556).usr/settings.jsonkeepsmcp_servers, a JSON string of MCP server definitions that can carry headers or env keys (settings.py:93);mcp_server_tokenis blanked (settings.py:553).- Legacy: root
.env,tmp/secrets.env,tmp/settings.json(migration.py:36-38); the VPS guide still mounts a root.env(docs/setup/vps-deployment.md:176). - The desktop plugin keeps a profile with
.ssh/and.gnupg/underusr/plugins/_desktop/profiles/agent-zero-desktop/(paths from a grep of string literals; writer not traced). usr/plugins/<plugin>/config.jsonholds a plugin's settings, which for the Telegram integration are the bottokenand, in webhook mode,webhook_secret, and probably the email integration's credentials (helpers/plugins.py:838-851); secret globsagent-zero*/usr/plugins/*/config.json,Desktop/agent-zero*/usr/plugins/*/config.jsonand the volume-relativeplugins/*/config.json(thea0_usrvolume's base isusritself) andusr/plugins/*/config.jsonfrom collector 1.14.0. No otherDOCKER_VOLUMESlayout has aplugins/<name>/config.json. A per-project copy under.a0proj/or an agent profile's directory is not flagged. Each Telegram chat'schat.jsonrepeats the values (Secrets).- Host side:
~/.agent-zero/session_cookies.json(login cookies per host,config.py:123-146); the launcher'sstate.jsonstores instance passwords encrypted with ElectronsafeStorage, i.e. the OS keychain (state_store.js:683-688,753-761). - WhatsApp: the bridge, a Node.js process that signs in as a linked WhatsApp
device through the Baileys library, keeps that device's login state in
tmp/whatsapp/session/with Baileys'useMultiFileAuthState(plugins/_whatsapp_integration/helpers/storage_paths.py:6-7,whatsapp-bridge/bridge.js:46,108). Whoever holds those files can act as the account's linked device; the directory is collected wheretmp/is on the host, flagged by the secret globsagent-zero*/tmp/whatsapp/session/*,Desktop/agent-zero*/tmp/whatsapp/session/*and the volume-relativetmp/whatsapp/session/*(no otherDOCKER_VOLUMESlayout has atmp/whatsapp/). The bridge had it ate3051fbalready. - OAuth model providers: the bundled
_oauthplugin signs in to GitHub Copilot (a GitHub device flow with the scoperead:user), Gemini and xAI Grok and keeps each provider's tokens inusr/plugins/_oauth/<provider>/auth.json(github_copilot,gemini_api,xai_grok), written with mode 0600 (plugins/_oauth/helpers/providers/base.py:151-173,197-216;plugins/_oauth/helpers/providers/github_copilot.py:170-177,519-525,571;plugins/_oauth/helpers/providers/gemini_api.py:59;plugins/_oauth/helpers/providers/xai_grok.py:60). The Copilot file holds the GitHub token asrefreshand the Copilot token asaccess. The files are collected withusr/and no secret glob flags them:plugins/*/config.jsonnames only the configuration file. - The connector's
.envalso holdsAGENT_ZERO_COMPUTER_USE_RESTORE_TOKEN(config.py:22), already covered by the.agent-zero/.envglob.
Exclusions¶
tmp/memory/embeddings is an embedding cache
(memory.py:145-147),
tmp/playwright holds browser binaries
(plugins/_browser/helpers/playwright.py:16),
usr/.time_travel is shadow git. For native clones: .venv, .conda, .git. Python environments
inside usr/workdir/*/.venv occur (the code references one). The connector's and launcher's
Chromium directories are caches and cookie stores.
The usr/.time_travel exclusion drops more than file contents: every snapshot commit names the
chat that caused it, so the shadow git is a record of which chat changed which files that outlives
a chat delete (Records of past use).
Its size was not measured. The launcher's WSL directory on Windows is a whole Linux disk and is not
a candidate for collection by default.
Project-local files¶
Agent Zero "projects" are directories it owns under usr/projects/<name> (git clones are made
there,
projects.py:121-151)
with metadata in .a0proj/; they are collected with usr/. Through the A0 CLI connector the
containerised agent reads and writes files and runs commands in the host's current directory
(acp.py:314,
session.py:119)
but writes no Agent Zero state file there.
Where the project path is recorded¶
usr/chats/<ctxid>/chat.json key data.project holds the project name
(projects.py:27,457);
the path is usr/projects/<name>.
A host repository path is recorded too. A chat opened by an editor through ACP, which the
connector's a0 acp command serves, stores the editor's workspace on the user's host as
data.acp_cwd and any extra folders as data.acp_additional_directories
(Editor sessions). The chat.json is on the host only
where usr/ is (installer, launcher host-directory mode, a native run) or in a collected volume,
and the path names a directory on whichever host ran the editor, which need not be the host running
Agent Zero. Project discovery in both collectors reads both keys from the chats of a home install
(not from a Docker volume), and the parser takes acp_cwd as the chat's project path
(Parser plan). A plain A0 CLI chat records no host path: the connector's working
directory stays on the host side
(a0-connector session.py:131);
no key for it was found in agent-zero's plugins/_a0_connector at ff2a5b9
(grepped for workspace and cwd).
Parsing¶
Transcript stores¶
Relative to the install directory (/a0 in Docker; on the host usually
~/agent-zero/<instance>/ for installer and launcher setups):
usr/chats/<ctxid>/chat.json, one per chat or task context; background contexts are never saved (helpers/persist_chat.py:17-19,50-60,95-96). The file is rewritten whole and atomically (99-120).ctxidis 8 random alphanumerics (agent.py:150-158).usr/chats/<ctxid>/messages/<n>.txt: full text of each tool result of 500 characters or more; the history record gets afilekey pointing at it (extensions/python/hist_add_tool_result/_90_save_tool_call_file.py:23-43).- Legacy:
usr/chats/<ctxid>.json(v0.8.0, moved into the folder layout on load,persist_chat.py:134-140) andtmp/chats/(moved tousr/chats,helpers/migration.py:24).
The catalog globs are therefore agent-zero/*/usr/chats/*/chat.json,
agent-zero/usr/chats/*/chat.json and the Desktop/agent-zero equivalents. A Docker volume holding
/a0/usr (a0_usr, a0-launcher-<slug>-usr) is collected with its _data directory as the base,
so its chats are chats/<ctxid>/chat.json relative to that base
(README.md:92,
shell/docker_manager/index.js:948-951).
The parser selects both forms (Parser plan). The volume layout has no real
install behind it (Observed).
What survives a delete¶
Deleting a chat removes its folder, usr/chats/<ctxid>/ with chat.json and messages/, and the
scheduler tasks bound to it, and asks the provider to delete the chat's stored responses; a reset
rewrites chat.json and removes messages/
(api/chat_remove.py:11-26,
api/chat_reset.py:13-19).
The provider call's errors are discarded, so nothing local says whether the remote copy went
(Sync, relay and origin).
After a delete the
time-travel shadow git of usr, the memory store, the received files
(usr/uploads/, usr/email/attachments/ and the WhatsApp media
directories) and the Telegram plugin's state.json remain; state.json
still maps the Telegram user and chat to the old ctxid until that
user writes again, so an entry with no chat.json is a deleted
Telegram chat, the only deletion marker. The scheduler's tasks.json
outlives a reset of a task's chat but not a delete
(Other stores). Whether Agent Zero
keeps a per-prompt history file is not stated.
The analyzer reads the scheduler's tasks.json and the Telegram
state.json as secondary sources, the second giving a deletion row for a
mapped chat that is gone
(Past use and secondary sources,
Secondary sources); it does
not read tasks.yaml, the time-travel git, which the collector excludes,
or the memory store, a pickle left to manual analysis.
Record schema¶
chat.json top level
(persist_chat.py:179-219):
id, name, created_at, last_message (ISO 8601 with the user's UTC offset,
helpers/localization.py:195-212),
type (user or task,
agent.py:50-53),
agents, streaming_agent, agent_profile, log, data (includes project), output_data.
Agent history¶
agents[]
(persist_chat.py:222-232):
agent 0 first, then each subordinate. Fields number, agent_profile, data, and history, which
is a JSON string (compact dump,
helpers/history.py:520-522,810-811)
that decodes to {"_cls":"History","counter","bulks":[],"topics":[],"current":{}}
(history.py:512-518).
A Topic is {_cls, summary, messages}
(290-295),
a Bulk is {_cls, summary, records} of topics or bulks
(340-345).
A Message is {_cls:"Message", id, ai, content, metadata, sequence, summary, tokens}
(138-149),
no timestamp. Chronological order is bulks, then topics, then current, messages in list order.
Message content by kind:
- User (
ai=false): dict fromfw.user_message.md,{system_message?, user_message, attachments?}with empty keys removed (agent.py:746-773,prompts/fw.user_message.md). - Assistant (
ai=true): the model's text, which in the default prompt mode is a JSON object{thoughts, headline, tool_name, tool_args}(prompts/agent.system.main.communication.md:9-12); with native function calling it is{"tool_name","tool_args"}rendered from the calls, orparallel_tool_callswrapping several (agent.py:775-795,helpers/llm_result.py:197-209).metadata.responsescarriesresponse_id,provider_model_key,usage(llm_result.py:227-239). - Tool result (
ai=false): dict{tool_name, tool_result, file?, ...}(agent.py:802-825); the messageidis the tool's log item id (helpers/tool.py:56,61-68).
Log¶
log
(persist_chat.py:235-247):
{guid, logs, progress, progress_no}, logs being the last 1000 items
(persist_chat.py:18).
Each item
(helpers/log.py:199-209):
no, id, type, heading, content, kvps, timestamp (float epoch seconds, time.time(),
log.py:157-162),
agentno. type is one of agent, browser, code_exe, subagent, error, hint, info,
progress, response, tool, mcp, input, user, util, warning
(log.py:44-60).
Content is cut to 15,000 characters
(log.py:66,124-135).
Keys passed as keyword arguments are merged into kvps
(log.py:336-340):
useritems:contentis the message,idthe history message id (helpers/message_queue.py:141-147).agentitems: the streamed generation;kvpsholds the parsed response (thoughts,headline,tool_name,tool_args),step,reasoning(extensions/python/response_stream/_10_log_from_stream.py:47-69).toolitems:kvpsis the tool arguments plus_tool_name;contentis later set to the result (helpers/tool.py:56-59,68).responseitems: the final answer to the user.
Remote-copy keys¶
Keys in data and agents[].data that record a remote copy. Context and agent data are saved
without the keys that start with _
(helpers/persist_chat.py:194-195,223),
so these survive:
agents[].data.responses_state, written after each model reply that carries a provider response id (agent.py:1062-1082):{response_id, previous_response_id, provider_model_key, history_counter, response_ids: [...]}, all strings buthistory_counter(the historysequenceof the reply) andresponse_ids(every id the chat has had for that model). The Responses API is OpenAI's generation endpoint, which can keep each response on the provider's side (store: true) so the next turn sends onlyprevious_response_idand the new input. Agent Zero calls providers through the litellm library, and its transport setsstore: truewhen the model'sresponses_stateisprovider, which is the value when none is set, andstore: falseforlocalandoff(helpers/litellm_transport.py:889-904,1554-1556). It applies only to a model whosea0_api_modeisresponses; every stock provider inconf/model_providers.yamlischat, which sets the state tooff(105-112), and the bundled Codex (ChatGPT account) provider isresponseswithresponses_state: local(plugins/_oauth/conf/model_providers.yaml:9-10). So a key present means the provider returned response ids, not that it stored them; a non-emptyprevious_response_idmeans a turn was chained on a stored response. History compression and manual compaction dropresponse_idandprevious_response_idbut keepresponse_ids(helpers/history.py:736-755,extensions/python/message_loop_end/_10_organize_history.py:12,plugins/_chat_compaction/helpers/compactor.py:149); a branched chat drops the whole key (plugins/_chat_branching/api/branch_chat.py:142-144). The same id is also in each assistant message'smetadata.responses(Agent history).- Telegram chats (the bundled
_telegram_integrationplugin, a bot the user runs with a token from Telegram):data.telegram_bot(bot name),telegram_chat_id,telegram_chat_type,telegram_user_id,telegram_usernameandtelegram_bot_cfg, the bot's whole configuration entry (plugins/_telegram_integration/helpers/constants.py:5-15,plugins/_telegram_integration/helpers/handler.py:380-400); the chat is namedTelegram: @<username>orTelegram: <user id>(391-392). - WhatsApp chats (
_whatsapp_integration):data.wa_chat_id,wa_sender_name,wa_sender_number,wa_is_group,wa_active,wa_last_body,wa_last_msg_id(plugins/_whatsapp_integration/helpers/handler.py:33-39,153-159). - Email chats (
_email_integration, IMAP in and SMTP out):data.email_handler,email_sender,email_thread_id,email_subject,email_message_id,email_references,email_last_body(plugins/_email_integration/helpers/dispatcher.py:14-21,269-270).
Editor sessions¶
Read by the parser (Parser plan). ACP lets an editor drive an agent; the bundled
_a0_acp plugin serves it and the host-side connector (a0 acp) relays the editor's files and
terminal. A chat an editor
opens gets data.acp_session (true), acp_cwd (the editor's workspace, a path on the user's
host), acp_additional_directories (a list of paths), acp_mode (default, plan or act,
anything else stored as default), acp_transport (connector or container), acp_model_id,
acp_config_options, and, for the container transport with a configured root, workdir_path (a
working directory inside the container); the chat is named after the last component of acp_cwd
(plugins/_a0_acp/api/session.py:12-20,41-43,131-150).
The keys are written at e3051fb as well.
Model override¶
Read by the parser (Model rows). Choosing a model for one chat stores
data.chat_model_override: {"preset_name": <name>} for a preset of
usr/plugins/_model_config/presets.yaml, a whole model configuration object for a custom choice, or
null when cleared
(plugins/_model_config/api/model_override.py:58,81,92,
plugins/_model_config/helpers/model_config.py:10,744-756);
the connector's model switcher writes the same key as {"chat": {...}, "utility": {...},
"embedding": {...}}, each slot {provider, name, api_key?, api_base?}
(plugins/_a0_connector/api/v1/model_switcher.py:27-46,200-211),
so a custom choice can carry an API key (Secrets).
Only the latest choice is kept, so the history of switches is the per-message provider_model_key.
Joins and timestamps¶
- Chat to project:
data.projectis a project name; path/a0/usr/projects/<name>(helpers/projects.py:457). Without a project the working directory isusr/workdir. - Log to history:
log.logs[].idequals the historyMessage.idfor user messages and tool results (Record schema). - Tool use to result: one
toollog item holds both; in history the assistant message'stool_nameand the next tool-result message. - Parent to subordinate:
agents[n]is the subordinate ofagents[n-1](persist_chat.py:189-194); log items carryagentno. - Times: log items carry float epoch seconds, history messages none, and
created_atandlast_messageare ISO 8601 with the user's UTC offset (Log, Agent history).
Other stores¶
Beside chat.json, the transcript store, Agent Zero keeps the stores below. Memory is a FAISS
index plus a pickled LangChain docstore (usr/memory/<subdir>/index.pkl); reading it means
unpickling untrusted data, so leave it to manual analysis.
Records of past use¶
Cited at ff2a5b9.
The parser reads the scheduler's tasks.json and the Telegram state.json; the plan marks each
source in Past use and secondary sources. Paths are relative
to the install directory.
| File | Holds | Survives | Joins chat.json on |
Kind |
|---|---|---|---|---|
usr/scheduler/tasks.json, or tasks.yaml when only that exists |
One object per scheduled, ad hoc or planned task: uuid, context_id, name, system_prompt, prompt, attachments, project_name, created_at, updated_at, last_run, last_result, state, type (helpers/task_scheduler.py:163-175,512-515) |
A reset of the task's chat; not a chat delete, which removes the tasks bound to the chat (api/chat_remove.py:24-26) |
context_id = id; prompt repeats the task chat's user message, last_result its last answer (Scheduler tasks) |
secondary, parsed (tasks.json only) |
usr/plugins/_telegram_integration/state.json |
chats, "<bot>:<user id>:<chat id>" to ctxid (Telegram chat map) |
A chat delete, until that Telegram user writes again | the ctxid value = id |
secondary, parsed (a deletion marker: an entry with no chat.json) |
usr/.time_travel/workspaces/ |
A shadow git repository per workspace of usr, snapshotted automatically; each commit message ends with A0-Time-Travel-Metadata: and base64 JSON with context_id, project_name, trigger, timestamp and changed_path_hints (plugins/_time_travel/helpers/time_travel.py:22-28,1192-1194,1206-1220) |
A chat delete and the deletion of the files it wrote | context_id = id, and time |
secondary; excluded by the collector (usr/.time_travel), so not in a collection |
usr/memory/<subdir>/index.pkl |
Memory fragments and solutions the agent summarised at the end of each monologue, with id, timestamp and area and no chat id (plugins/_memory/helpers/memory.py:475-487) |
A chat delete or reset | time only | secondary; a pickle, left to manual analysis |
usr/email/state.json |
The IMAP message ids already processed per handler (plugins/_email_integration/helpers/handler.py:38-39) |
A chat delete | nothing | no events |
usr/uploads/, usr/email/attachments/, usr/whatsapp/media/ and tmp/whatsapp/media/ |
Files received through the web UI, Telegram, email and WhatsApp (plugins/_telegram_integration/helpers/constants.py:2, plugins/_whatsapp_integration/helpers/handler.py:31, plugins/_whatsapp_integration/helpers/storage_paths.py:10-11) |
A chat delete | file names in user log items' attachments |
evidence files, no events |
The WhatsApp bridge keeps no message store: its only file writes are media
(plugins/_whatsapp_integration/whatsapp-bridge/bridge.js:311,323),
and its session directory tmp/whatsapp/session/ is the linked device's login state
(Credentials).
Telegram chat map¶
Telegram also keeps usr/plugins/_telegram_integration/state.json,
{"chats": {"<bot>:<user id>:<chat id>": "<ctxid>"}}, written when a Telegram user's first message
creates a chat
(plugins/_telegram_integration/helpers/constants.py:3,
plugins/_telegram_integration/helpers/handler.py:57-64,405-410).
The bot name is the part before the last two colons.
Scheduler tasks¶
usr/scheduler/tasks.json is the scheduler's task list as pydantic writes it, {"tasks": [...]},
each task an object with the keys of the Records of past use table,
datetimes as ISO 8601 strings, and type one of adhoc, scheduled and planned; state is
idle, running, disabled or error
(helpers/task_scheduler.py:78-88,512-519,584-592).
A scheduled task also holds schedule (cron fields), a planned task plan (todo,
in_progress, done), and an ad hoc task token
(332,422,
282-284).
A run logs the chat's user message as ## Task:\n<prompt>, or
## Context:\n<context>\n\n## Task:\n<prompt> when the task has context
(945-959),
and a finished run sets last_run and last_result, the monologue's answer or ERROR: <error>
with state error
(249-275).
Format versions¶
No version field. History compression summarises topics into bulks and drops the oldest bulk when
merging fails
(history.py:600-607),
so early turns may survive only as summaries in history and only in the log while it is under 1000
items. Older chats used chat.json-less <ctxid>.json files
(Transcript stores).
Between e3051fb and ff2a5b9 the drift is small: the usr/ layout is unchanged, the chat.json writer is
unchanged and six lines lower in helpers/persist_chat.py (_serialize_context at
185-253),
metadata.responses gains an optional history_extras string
(helpers/llm_result.py:249),
and the scheduler may keep tasks.yaml instead of tasks.json
(Per-user storage). The log, history and tool-result files the parser reads are
the same.
Secrets¶
Values from secrets.env are masked in history content and log items before storage
(extensions/python/hist_add_before/_10_mask_content.py:20-28,
log.py:420-435).
API keys in usr/.env are not in that set, so any key the user pastes or a tool prints stays in
clear text. user_message and tool kvps are the places to look.
A Telegram chat's data.telegram_bot_cfg is the bot's configuration entry as the bot loop holds it,
so it carries the bot token and, in webhook mode, webhook_secret, in clear text in chat.json
(plugins/_telegram_integration/extensions/python/job_loop/_10_telegram_bot.py:57-59,82-89,
plugins/_telegram_integration/default_config.yaml:2-9).
The transcript cannot be flagged, so token and webhook_secret are the keys to redact before
sharing a chat.json. The same values are in the plugin's configuration file
(Credentials).
A chat's data.chat_model_override can hold an api_key in each slot of a custom choice made from
the connector (Model override), in clear text in chat.json; the parser prints
only each slot's provider and name. An ad hoc task's token in usr/scheduler/tasks.json is a
random 19-digit number the task is created with, whose use was not traced
(Scheduler tasks); the parser does not read it.
The WhatsApp bridge's login state is a credential directory, not a field of a store (Credentials).
Parser plan¶
Rows from log.logs (timestamped); when len(log.logs) == 1000, also emit
history messages that have no matching log id, with an empty timestamp and
a system row saying the log was trimmed.
Paths: chat.json, its messages/<n>.txt and the legacy <ctxid>.json
under <a0>/usr/chats or <a0>/tmp/chats of a home install, and under
chats/ at the base of a Docker volume mounted at /a0/usr
(issue 175,
Transcript stores); the rows are the same in both forms.
Beside them, in the same two forms: usr/scheduler/tasks.json (or the
legacy tmp/scheduler/tasks.json), usr/plugins/_telegram_integration/state.json,
each _tool_access/config.json and _orchestrator/config.json, the
.toggle-0 and .toggle-1 files of _infection_check and _orchestrator
at every plugin scope (Per-user storage), and
~/.agent-zero/.env of the connector.
| Column | Source |
|---|---|
| timestamp_utc | log timestamp (epoch s) |
| session_id | chat.json id |
| project_path | data.acp_cwd for an editor session, else /a0/usr/projects/<data.project>, else empty |
| git_branch | empty |
| turn_type | user → user; response → assistant; agent → assistant (kvps.headline/thoughts), and thinking for kvps.reasoning; tool, mcp, code_exe, browser, subagent → tool_use then tool_result from content; others → system |
| model | metadata.responses.provider_model_key of the matching assistant message, else empty |
| tool_name | kvps._tool_name |
| tool_use_id | log item id |
| text | content; for tool_use the code/command/url key of kvps, else kvps as JSON |
| source_line | log item no |
The subsections below give one paragraph per class, from source at ff2a5b9; every row
they describe is written by the parser.
Permission rows¶
Every row below is source-derived; not observed on any real install.
Per call. A tool call the profile's policy blocks raises
Tool "<name>" is blocked for agent profile "<profile>"., which the agent records as a history
warning and a warning log item with the same id
(helpers/tool_policy.py:197-208,
extensions/python/_functions/agent/Agent/handle_exception/end/_50_handle_repairable_exception.py:17-22):
permission decision: blocked tool=<name> profile=<profile>. A provider-hosted MCP approval request
on the Responses API is always denied, logged as a warning headed
Responses MCP approval required with a tool result mcp_approval_request
(agent.py:1325-1346):
permission decision: denied automatically (provider MCP approval request). The Infection Check
plugin, a reviewer model that audits the agent's output before each tool runs, is disabled by
default (the bundled plugins/_infection_check/.toggle-0; a plugin is switched by a .toggle-0 or
.toggle-1 file,
helpers/plugins.py:60-61,505-510);
when enabled, a pass leaves only a progress line, and a question or a stop leaves warning items
headed Infection check: requesting clarification, Infection check: clarification passed or
Infection check: TERMINATED, the last also replacing the agent's last history message with a
blocked marker
(plugins/_infection_check/helpers/checker.py:180-197,330-345):
permission decision: <clarify, passed or terminated> (infection check). Each decision row follows
the system row warning: <heading> | <content> of the log item it reads, at the item's time;
the blocked row carries the tool's name in tool_name and the MCP row mcp_approval_request. No
log field joins a decision to the call it governed, so tool_use_id stays empty.
Standing. Tool policies are mode (inherit or custom), default and mcp_default (allow or
block), allowed and blocked lists of tool ids
(plugins/_tool_access/default_config.yaml:1-5,
helpers/tool_policy.py:27-37,176-195),
in usr/agents/<profile>/plugins/_tool_access/config.json, a project's
.a0proj/plugins/_tool_access/config.json and
.a0proj/agents/<profile>/plugins/_tool_access/config.json
(plugins/_tool_access/README.md:4-9):
one
permission setting: tool_access.<key>=<value>[ profile=<profile>][ project=<name>] (from <file>, file mtime)
row per scalar key and list entry, the profile and project taken from the file's
path, with an empty session_id and, for a project's file, project_path the project. The
Orchestrator plugin, which tells the agent how to run other coding CLIs on the user's host or in
the container, defaults each to its approval bypass (bypass_sandbox,
permission_mode: bypassPermissions, force, always_approve, yolo, auto,
plugins/_orchestrator/default_config.yaml:7-37);
a user override in usr/plugins/_orchestrator/config.json gives one
permission setting: orchestrator.<cli>.<key>=<value> (from <file>, file mtime) row for each of
those seven keys it holds, and nothing else of the file is read. A .toggle-1 or .toggle-0 of
_infection_check or _orchestrator at any plugin scope gives
permission setting: <infection_check|orchestrator>=<enabled|disabled>[ profile=<profile>][ project=<name>] (from <file>, file mtime).
An editor session's data.acp_mode gives permission mode: <acp_mode> (acp, as of file mtime)
after the chat start row, at the file's modification time, since only the latest mode is kept.
Model rows¶
Before an agent log item, or a history-only
assistant message when the log was trimmed, whose
metadata.responses.provider_model_key is new for that agent, a system
row model: <key> at the agent's first model and model: <old> -> <new>
on a change, tracked per chat id and agent number (agentno on log
items), with agent=<n> after it for a subordinate agent. These model: rows from
provider_model_key are already written.
After the chat start row, at the file's modification time, source-derived; not observed on any
real install:
model: requested <acp_model_id> (acp, as of file mtime) from
data.acp_model_id, and model: requested <choice> (chat override, as of
file mtime) from data.chat_model_override, where <choice> is
preset <preset_name>, or <slot>=<provider>/<name> for each slot of a
custom choice (chat, utility, embedding), or the top-level
<provider>/<name>, or custom configuration; the object itself is never
printed, since it can hold an api_key
(Model override, Editor sessions).
A cleared override (null) gives no row.
Past-use rows and secondary sources¶
For the sources table in Records of past use,
source-derived; not observed on any real install. usr/scheduler/tasks.json is secondary: per
task, with
session_id the context_id and project_path
/a0/usr/projects/<project_name> when set, a system row
scheduled task: <name> type=<type> state=<state> at created_at, a
user row ## Task:\n<prompt> with no timestamp (the text a run logs as
the chat's user message when the task has no context,
Scheduler tasks), and the last_result at last_run
as an assistant row, or as a system row
scheduled task failed: <error> when the state is error and the result
starts ERROR: . last_run is stamped when the run ends, after the
chat's response log item, so the file's matching window is 60 seconds.
token and system_prompt are not read, and tasks.yaml is not read
(YAML, which the analyzer has no reader for). state.json of the Telegram
plugin is secondary: one
session deleted: telegram bot <bot> chat <chat id> user <user id> ctxid <ctxid> (from state.json, no chat.json in the input, file mtime)
row, with session_id the ctxid, for each map entry whose
chats/<ctxid>/chat.json or chats/<ctxid>.json is not beside it in the
input. The time-travel git and the memory pickle are not parsed.
Sync, relay and origin rows¶
Sync: Agent Zero records no sync state. It has no account, cloud copy, share link or history sync:
the web UI is served by the instance itself, and the features that move chats are local. Backup
builds a zip of usr/ and sends it to the browser as a download
(helpers/backup.py:338-432,
api/backup_create.py:35-51);
chat export returns the chat.json text to the browser
(api/chat_export.py:5-17,
helpers/persist_chat.py:155-159);
the Remote Control tunnels (Serveo, Cloudflare, Microsoft, Tailscale) expose the web UI and persist
nothing
(helpers/tunnel_manager.py:15-31);
the only call to the vendor's own service is the update check, which posts the version and a hashed
install id, no chat content, and is on by default (update_check_enabled in usr/settings.json,
helpers/update_check.py:5-19,
helpers/settings.py:627,
extensions/python/user_message_ui/_10_update_check.py:66);
and the host-side A0 CLI connector talks to the user's instance and to GitHub for its own updates
(a0-connector self_update.py:20-25).
Searched sync, share, upload, cloud, publish, remote_id, telemetry, analytics,
agent-zero.ai and every https:// host across both repositories. Two features leave a copy of a
chat on a third party's server, and chat.json records each
(Remote-copy keys); both are implemented and unchanged at the 2026-10-19 HEAD:
- Stored responses. With a model set to
a0_api_mode: responsesand noresponses_state(orprovider), each reply is stored at the provider;agents[].data.responses_stateandmetadata.responses.response_idhold the ids. The parser yields one row per agent whoseprevious_response_idis non-empty:session synced: provider response <response_id or -> previous <previous_response_id> model <provider_model_key or -> (<n> response ids) agent=<number> (from chat.json agents[].data.responses_state, file mtime), timestamped by the file's modification time, and setsrecords_sync. Becauselocalmode records the same ids withstore: false, an agent whoseprevious_response_idis empty yields no row. Fixture only: no real install has shown the key. On chat delete, Agent Zero collects every response id inchat.jsonand calls litellm'sdelete_responsesfor each unlessresponses_delete_on_chat_deleteisfalsein the model's kwargs or the chat data, then deletes the folder (helpers/persist_chat.py:162-168,390-450,agent.py:941-942); the call passes no provider or key and its error list is discarded (helpers/litellm_transport.py:1481-1490), so nothing local says whether the remote copy went. - Messaging channels. A Telegram, WhatsApp or email chat is carried by that service, which keeps the
messages; no Discord, Slack or other channel exists at
ff2a5b9(grepped fordiscord,slack,mattermostandsignal-cli: only an unrelated office helper matches). The parser yields one row per chat and channel with the keys:session relayed: telegram bot <telegram_bot> chat <telegram_chat_id> user <telegram_user_id> @<telegram_username or -> (from chat.json data, file mtime),session relayed: whatsapp chat <wa_chat_id> number <wa_sender_number or -> (from chat.json data, file mtime)orsession relayed: email thread <email_thread_id or -> from <email_sender or -> (from chat.json data, file mtime), timestamped by the file's modification time, and never printstelegram_bot_cfg(it holds the bot token, Secrets). Fixture only. Deleting the chat removes the folder, but Telegram'sstate.jsonstill maps the user and chat to the oldctxiduntil that user writes again (plugins/_telegram_integration/helpers/handler.py:376-387), so astate.jsonentry with nochat.jsonis a deleted Telegram chat.
Origin: none on the instance, but the connector's ~/.agent-zero/.env names the last chat it
used on a remote instance (AGENT_ZERO_LAST_CONTEXT_ID and AGENT_ZERO_LAST_CONTEXT_HOST,
a0-connector config.py:13-14,
written together by
347-356). When both are set the parser
yields
session origin: remote agent-zero instance <AGENT_ZERO_LAST_CONTEXT_HOST> context <AGENT_ZERO_LAST_CONTEXT_ID> (from .agent-zero/.env, file mtime)
with session_id the context id, at the file's modification time, and sets records_origin;
source-derived; not observed on any real install. It reads only those two keys of a file the
collector flags as a secret, strips quotes as the connector's own reader does
(51-66), and puts no other line in a row.
Scratch directory rows¶
A chat with no project runs in /a0/usr/workdir (the default workdir_path,
helpers/settings.py:604),
and the analyzer's catalog rule cannot class a container path. An editor session that sets
data.workdir_path gives
scratch directory: <workdir_path> (acp container transport, from chat.json data.workdir_path, as of file mtime)
after the chat start row, at the file's modification time, with project_path the directory;
source-derived; not observed on any real install.
An editor session's data.acp_cwd, the user's project on the host, is the project_path of its
other rows. A chat with no project and no editor session gets no scratch row: the working
directory it ran in is the instance's workdir_path setting, not a key of the chat. The host
connector's computer-use screenshot directory is described in
Host-side companions.
Deletion rows¶
A chat delete also removes the chat's scheduler tasks;
what survives it is Telegram's state.json, the time-travel git, the
memory store and the received files (What survives a delete).
Nothing local says whether the provider deleted its stored responses
(Sync, relay and origin). The deletion row is the Telegram map's
session deleted: row under
Past use and secondary sources, source-derived; not observed on any real install.
Bad-line rows¶
No file is read line by line. A chat.json that does not parse yields a whole-file row plus the
log items the parser can recover. tasks.json is a JSON array reader: a task that is not an object
gives parser: unparseable record <N> (not a JSON object): <record> and the tasks around it are
still read, and a file that is not JSON or has no tasks list gives one
parser: scheduler tasks file ... row. state.json and the policy files give one whole-file
parser: row when they are not JSON objects. The connector's .env gives no bad-line rows: it is
a secret file, and the connector's own reader skips a line without = too.
Fixtures¶
Fixture usr/chats/AbCd1234/chat.json:
{"id":"AbCd1234","name":"List files","created_at":"2026-10-01T14:00:00+02:00","type":"user",
"last_message":"2026-10-01T14:00:05+02:00","streaming_agent":0,"agent_profile":"agent0",
"data":{"project":"demo"},"output_data":{},
"agents":[{"number":0,"agent_profile":"agent0","data":{},
"history":"{\"_cls\":\"History\",\"counter\":3,\"bulks\":[],\"topics\":[],\"current\":{\"_cls\":\"Topic\",\"summary\":\"\",\"messages\":[{\"_cls\":\"Message\",\"id\":\"u1\",\"ai\":false,\"content\":{\"user_message\":\"list files\"},\"metadata\":{},\"sequence\":0,\"summary\":\"\",\"tokens\":5},{\"_cls\":\"Message\",\"id\":\"a1\",\"ai\":true,\"content\":\"{\\\"thoughts\\\":[\\\"list\\\"],\\\"headline\\\":\\\"Listing\\\",\\\"tool_name\\\":\\\"code_execution_tool\\\",\\\"tool_args\\\":{\\\"runtime\\\":\\\"terminal\\\",\\\"code\\\":\\\"ls\\\"}}\",\"metadata\":{},\"sequence\":0,\"summary\":\"\",\"tokens\":30},{\"_cls\":\"Message\",\"id\":\"t1\",\"ai\":false,\"content\":{\"tool_name\":\"code_execution_tool\",\"tool_result\":\"a.txt\"},\"metadata\":{},\"sequence\":0,\"summary\":\"\",\"tokens\":8}]}}"}],
"log":{"guid":"6b0f0c1e-0000-4000-8000-000000000001","progress":"","progress_no":3,"logs":[
{"no":0,"id":"u1","type":"user","heading":"","content":"list files","kvps":{"attachments":[]},"timestamp":1759320001.0,"agentno":0},
{"no":1,"id":"g1","type":"agent","heading":"A0: Listing","content":"","kvps":{"step":"Writing terminal command... (2)","thoughts":["list"],"headline":"Listing","tool_name":"code_execution_tool","tool_args":{"runtime":"terminal","code":"ls"}},"timestamp":1759320002.0,"agentno":0},
{"no":2,"id":"t1","type":"tool","heading":"A0: Using tool 'code_execution_tool'","content":"a.txt","kvps":{"runtime":"terminal","code":"ls","_tool_name":"code_execution_tool"},"timestamp":1759320003.0,"agentno":0}]}}
Fixture usr/scheduler/tasks.json (one task shown; the test fixture also holds an ad hoc task in
state error with last_result ERROR: connection refused and a token):
{"tasks":[{"uuid":"TaskUuid01","context_id":"AbCd1234","state":"idle","name":"Nightly listing",
"system_prompt":"You run on a schedule.","prompt":"list files","attachments":[],
"project_name":"demo","created_at":"2026-10-01T11:00:00Z","updated_at":"2026-10-01T12:00:05.500000Z",
"last_run":"2026-10-01T12:00:05.500000Z","last_result":"There is one file, a.txt.",
"type":"scheduled","schedule":{"minute":"0","hour":"2","day":"*","month":"*","weekday":"*"}}]}
Fixture usr/plugins/_telegram_integration/state.json, whose second entry has no chat:
{"chats":{"opsbot:123456789:987654321":"TgChat01","opsbot:555:777":"GoneTg01"}}
Fixture usr/agents/developer/plugins/_tool_access/config.json:
{"mode":"custom","default":"allow","mcp_default":"block","allowed":[],
"blocked":["code_execution_tool","mcp:github.create_issue"]}
Fixture data of an editor-session chat, and its warning log items' headings: the blocked-tool
message in a formatted error, Responses MCP approval required,
Infection check: clarification passed and Infection check: TERMINATED:
{"project":"demo","acp_session":true,"acp_cwd":"/home/alice/src/webapp",
"acp_additional_directories":["/home/alice/src/shared"],"acp_mode":"act","acp_transport":"container",
"acp_model_id":"openai/gpt-5","acp_config_options":{},"workdir_path":"/a0/usr/workdir/acp",
"chat_model_override":{"chat":{"provider":"openrouter","name":"anthropic/claude-sonnet-4","api_key":"<redacted>"},
"utility":{"provider":"ollama","name":"qwen3"}}}
Fixture ~/.agent-zero/.env, with keys the parser must not read:
AGENT_ZERO_HOST=http://localhost:50080
AGENT_ZERO_COMPUTER_USE_RESTORE_TOKEN=<redacted>
AGENT_ZERO_LAST_CONTEXT_HOST=https://a0.example.net
AGENT_ZERO_LAST_CONTEXT_ID='RemCtx01'
Source host rows¶
The agent records no source-host integration. Grepped github, gitlab, bitbucket, oauth,
installation, repositor, pull request, clone and token across agent-zero at
ff2a5b9
and a0-connector at
3741c88.
Cloning a repository as a project takes a token for that one clone, passes it as an HTTP header and
never stores it (git_token is a transient key), and the project's .a0proj/project.json keeps
the clone URL with any credentials stripped
(helpers/projects.py:74,121-151;
helpers/git.py:433-454); the plugin installer's git_token is
used the same way
(plugins/_plugin_installer/api/plugin_install.py:47-53).
The GitHub Copilot sign-in of the _oauth plugin stores a GitHub token, but only to reach Copilot
models, with the scope read:user, and records no login (Credentials). No list of
repositories and no repository-bound remote conversation is kept. A clone URL is the project's own
git remote, not an integration, so the parser writes no source host: row.
Confidence¶
- High (source): every path under the install directory and its
usr/layout (constants), the installer and launcher defaults, the connector files. - High (source): the
chat.jsonfile layout, top-level keys, history and log item shapes, timestamp units and masking. - Medium: the Electron
userDatapaths for the launcher (Electron default fromproductName, nosetPathfound; Host-side companions). - Medium:
Desktop/agent-zero, which is only the docs example. - Medium: the exact
typeandheadingofcode_execution_toolitems (they come from a tool subclass not traced; the generictoolpath is shown). - Not determined: where native installs are cloned in practice; the catalog cannot find a clone outside the two listed paths.
- Not determined: the desktop plugin's credential files beyond the literal paths found.
- Medium (source, no real install): the permission, setting, requested-model, scratch, scheduler, Telegram deletion and connector origin rows (Parser plan); the heading and message texts they match are literals in source, but no install has shown them on disk.
- Not determined: the content of task-scheduler contexts beyond the logged prompt, what an ad hoc
task's
tokenis used for, and theresponsesmetadata for every provider.