daemon-manual · diff
v0.16.0 to v0.18.0
98 added, 200 removed. Audit A to A.
---
name: daemon-manual
description: >
- Read before delegating work, diagnosing a slow/stuck/failed/timed-out
- emanation, or reclaiming on a hunch. Routes daemon call shape, task context,
- settings, backend support, inspection, compaction, and cleanup procedures.
- version: 0.16.0
- last_changed_at: 2026-09-08T00:00:00Z
+ Use for unfamiliar daemon delegation, backend-specific work, stalled or
+ failed runs, completion checks, or consent-gated cleanup. Routine calls can
+ start from the advertised schema.
+ version: 0.18.0
+ last_changed_at: 2026-09-09T00:00:00Z
related_files:
- src/lingtai/tools/daemon/CONTRACT.md
- src/lingtai/tools/daemon/ANATOMY.md
- src/lingtai/services/daemon.py
- src/lingtai/cli_daemon.py
- tests/test_cli_daemon.py
- src/lingtai/tools/daemon/system_prompt.py
- src/lingtai/tools/daemon/settings.py
- src/lingtai/tools/daemon/execution_host.py
- src/lingtai/tools/daemon/shell_prompt_events.py
- src/lingtai/tools/daemon/manual/reference/forensics/SKILL.md
- - src/lingtai/tools/daemon/manual/reference/inspection/SKILL.md
- src/lingtai/tools/daemon/manual/reference/cli-backends/SKILL.md
- src/lingtai/tools/daemon/manual/reference/cleanup/SKILL.md
- src/lingtai/tools/daemon/manual/reference/dispatch-ledger/SKILL.md
- src/lingtai/tools/bash/manual/SKILL.md
- tests/test_daemon_settings.py
maintenance: |
- Keep this as a short router. Put backend recipes, artifact forensics,
- inspection cadence, ledger diagnosis, and cleanup detail in the nested
- references; keep links and settings anchors stable.
+ Keep this as the shortest Daemon router. Put backend recipes, artifact
+ forensics, ledger diagnosis, and cleanup detail in nested references.
+ Preserve capability-versus-permission and durable-store boundaries.
---
# Daemon Manual — Router
- `daemon` dispatches disposable subagents (emanations) with isolated sessions and
- bounded tools. Read this manual before the first call. Put the complete
- objective, authority, safety boundary, collaboration rules, and deliverable in
- each task's `task`; `tools` grants capability only. The daemon is not a durable
- persona or hidden memory store: leave reviewable work in files and use run
- artifacts for follow-up.
-
- ## Routing table
-
- | Need / keywords | Read |
- |---|---|
- | First use, safe call shape, task authority, settings, completion, or compact | This router, then the relevant section below |
- | `backend="lingtai"`; built-in/in-process backend; preset, skills, MCP, or `finish` behavior | `reference/cli-backends/reference/backends/lingtai/SKILL.md` directly; no generic CLI page is required |
- | External CLI backend, alias, resume, `backend_options`, native MCP/config, or installed `--help` | `reference/cli-backends/SKILL.md`, then its per-backend page |
- | `list`/`check` cadence, stall, reminder, or intervention | `reference/inspection/SKILL.md` |
- | Run artifacts, events, transcripts, token records, or SIGTERM/143 | `reference/forensics/SKILL.md` |
- | Dispatch-ledger warnings or runtime identity mismatch | `reference/dispatch-ledger/SKILL.md` |
- | Reclaim, footprint, consent-gated cleanup, or deletion boundary | `reference/cleanup/SKILL.md` |
- | Shell async events or shell-side supervision | `shell-manual` |
- | Programmatic use, CLI/help, or scripts/CI | `lingtai-agent daemon --help` |
-
- The built-in route is intentionally separate from the generic CLI route. The
- external page remains the owner of detailed CLI support, alias/resume behavior,
- MCP/config injection, reserved flags, auth hygiene, and per-backend discovery.
-
- ## Call shape and action choice
-
- Every call uses the closed LTP-v2 envelope. `input` contains only the selected
- action's fields; `reasoning` is required; root `summarize` is optional and is
- not action input. The optional root `summarize` boolean replaces the former flat `summary` field. An action's other fields are rejected before the engine runs.
-
- | Action | Example | Effect |
- |---|---|---|
- | `emanate` | `daemon(action="emanate", input={"tasks": [{"task": "...", "tools": ["file"]}]}, reasoning="...")` | dispatches |
- | `list` | `daemon(action="list", input={"status": "running"}, reasoning="...")` | read-only |
- | `ask` | `daemon(action="ask", input={"id": "run-id", "message": "..."}, reasoning="...")` | follow-up |
- | `check` | `daemon(action="check", input={"id": "run-id"}, reasoning="...")` | read-only |
- | `settings` | `daemon(action="settings", input={}, reasoning="inspect daemon settings")` | read-only |
- | `reclaim` | `daemon(action="reclaim", input={}, reasoning="stop confirmed work")` | cancels |
- | `manual` | `daemon(action="manual", input={}, reasoning="read procedures")` | read-only |
+ Use the advertised schema for routine calls. Read one direct owner below for an
+ unfamiliar or high-consequence workflow. Daemons are disposable workers in the
+ parent working directory, not durable persona, hidden memory, or authority to
+ widen the parent task.
- `manual` is directly callable and reaches no daemon engine. An `emanate` returns
- ids and a batch `group_id`; use each id/run id for inspection and audit. `list`, `check`, `settings`, and `manual` are read-only; `emanate`, `ask`, and `reclaim`
- are side-effectful. The terminal distinctions are fixed and cannot be inferred
- from a field borrowed from another action.
+ ## Safe first dispatch
- ## First dispatch: task context and boundaries
+ `task` is the complete parent-controlled objective, authority, approved paths,
+ safety/collaboration limits, tool policy, backend, and deliverable. `tools`
+ grants capability, not permission; never invent authority, broaden the task,
+ change credentials/configuration without approval, or infer daemon-manager
+ authority. Parent MCP tools are not inherited: pass complete one-run `mcp`
+ registrations when needed. Runtime redacts secret env/header values in prompt
+ context; do not replace required launch inputs with redaction placeholders.
- Each `tasks[]` item requires `task` and `tools`.
+ `task_files` are UTF-8 text inputs below the parent workdir. Preflight follows
+ symlinks, enforces containment/encoding/size, and content-addresses bytes into
+ the immutable read-only `daemons/_task_files/` store before scheduling. Workers
+ receive manifest metadata and snapshot paths, never mutable originals or embedded
+ contents. Any malformed, missing, out-of-root, oversized, or non-UTF-8 entry
+ rejects the whole batch; there is no original-path fallback.
- - **`task`** is the complete parent-controlled objective, authority, constraints,
- safety posture, collaboration rules, tool-use policy, and deliverable. The
- removed `system_prompt` field has no alias; put its instruction here.
- - **`tools`** grants technical capability, not permission beyond `task`. Parent
- MCP tools are not inherited. Guarded calls still pass the normal executor and
- call-guard path.
- - **`skills`** is an optional list of skill directories or `SKILL.md` paths.
- Relative paths use the parent working directory; runtime injects a compact
- frontmatter catalog and the worker reads selected skills when relevant.
- - **`mcp`** is an optional list of complete one-run stdio/http registrations.
- Names and shape remain visible while secret `env`/`headers` are redacted.
- LingTai mounts task-scoped clients; exposed tool names must be unique. External
- CLIs mount only transports documented in the backend reference.
- - **`plugin`** is an optional plugin directory or search-root list. A manifest
- becomes compact prompt context and merges its skills/MCP; missing or unreadable
- paths resolve to nothing.
- - **`task_files`** is an optional `{path, label?, role?}` UTF-8 text list under
- the parent working directory. Dispatch validates containment, encoding, and
- size, then snapshots bytes into the immutable store; the worker gets metadata
- and snapshot paths, never mutable originals or contents. A bad entry rejects
- the whole batch.
- - **`preset`** is an optional authorized `.json`/`.jsonc` path from
- `system(action="presets")`; use the full returned path. Omission inherits the
- parent's regular tools; MCP still needs explicit task registrations. An
- unauthorized preset is refused before loading or scheduling.
- - **`prompt`** is LingTai-only and is the first ordinary user message. Blank or
- omitted means exactly `Begin the assigned daemon task.`; external CLIs reject
- it and use `task` as their prompt.
- - **`backend_options`** is CLI-only passthrough: booleans emit flags, scalars
- values, lists repeat flags, false/null omit them, and reserved `env` supplies
- string environment overrides. Unsafe or harness-owned keys fail preflight;
- options apply at `emanate`, not `ask`. Run the installed CLI's `--help` first.
+ `backend="lingtai"` is the native in-process session: its explicit `preset`
+ comes from `system(action="presets")`, blank/omitted `prompt` means exactly
+ `Begin the assigned daemon task.`, and `finish(status="done")` is required
+ when `daemon_common` is present. External CLI backends use `task` as their
+ prompt input (the runner may add harness context), reject `prompt`, and do not
+ gain tools from `tools`; native MCP,
+ checkpoint, completion, and resume status is backend-specific. Use
+ `backend_options` only at `emanate` after checking the installed CLI `--help`.
- ### Per-task `context_token_limit`
+ ```jsonc
+ daemon(action="emanate", input={
+ "tasks": [{"task": "Do bounded work and leave reports/out.md.",
+ "tools": ["file"], "preset": "/approved/preset.json"}],
+ "backend": "lingtai"
+ }, reasoning="bounded delegation")
+ ```
- This is a provider-compaction threshold, not a daemon context or window setting.
- For native-provider support, resolved-window ownership, and failure behavior, use
- the built-in LingTai child route in the table above. External CLI backends ignore
- this field.
+ ## Actions and completion
- ## Backend choice and support
+ `emanate` dispatches ids plus `group_id`; `list` inspects the index; `ask` sends
+ a backend-specific follow-up; `check` reads state/events/artifact metadata and
+ durable result/error paths; `reclaim` cancels all running work owned by this manager, not one id,
+ and leaves evidence. Confirm the whole affected scope before calling it. `list`, `check`, `settings`, and `manual` are read-only; `emanate`, `ask`, and `reclaim` are side-effectful.
+ Example: `daemon(action="reclaim", input={}, reasoning="cancel all confirmed manager-owned work")`.
- `lingtai` is the default in-process backend. `claude-p` (alias `claude-code`),
- Codex, OpenCode, Qwen Code, and Kimi Code have source-backed native
- `daemon_common` checkpoint/completion paths as documented in the CLI reference.
- MiMo Code, Oh-My-Pi, Cursor, and DeepSeek retain prompt-catalog-only
- MCP/completion status; prompt text does not grant native tools. Hidden
- interactive Claude is for legacy stored runs, not new selection. Do not invent
- a fallback for an unsupported native path.
+ Every terminal outcome is published on the per-run daemon channel. Do not poll
+ to remain active: after notification call `check`, then open its durable result
+ or error path. `checkpoint` is live-only, bounded, cooperative, and nonterminal;
+ when present, call `finish` exactly once and use `done` only after validating the
+ requested result. A missing-finish failure is a completion-contract failure, not necessarily
+ a task failure: inspect the run's trace/result and the run directory's physical
+ `result.txt` even if `result_path` is null. Do not
+ background required validation and end expecting re-entry. Native LingTai `ask`
+ reaches live runs only; terminal resume is a separate supported-CLI capability.
- Before relying on an external CLI, inspect its installed `--help`. `tools` in
- the task is ignored by external CLIs; `prompt` is LingTai-only. CLI backend
- support, aliases, resume limits, reserved options, auth, and native MCP
- boundaries belong to `reference/cli-backends/SKILL.md` and its child pages.
+ The optional root `summarize` boolean replaces the former flat `summary` field.
+ LingTai workers receive `compact`: `compact(action="manual")` is read-only and
+ `compact(action="run", _reason="...")` is a repeatable sole-call, nonterminal
+ context reset. Do not use the unavailable parent `system.summarize`.
## Settings inventory (SHOW only)
Call `daemon(action="settings", input={}, reasoning="inspect daemon settings")`.
- Success is exactly `{"settings": [...]}` with row fields `key`, `current`,
- `default`, `configurable`, and `comment`. This action has no set/reset input and
- writes no files, environment, launcher state, or run. `configurable: true` means
- an owner procedure exists; it grants no mutation authority. A serialization/read
- failure returns `SETTINGS_UNAVAILABLE`, never partial rows.
+ Rows contain exactly `key`, `current`, `default`, `configurable`, and `comment`;
+ `SETTINGS_UNAVAILABLE` fails the whole action. `configurable: true` points to
+ an owner procedure and grants no mutation authority. SHOW never mutates settings. After an authorized source change, reconstruct the
+ owning manager at an approved safe boundary and verify SHOW again; editing a file
+ or environment does not update an existing manager. Never interrupt held work.
### Max turns
- Anchor: `daemon-manual#max-turns`. Current value and application belong to
- `daemon.settings`; precedence and setup details belong to the Contract. Per-call
- `emanate.max_turns` may choose a smaller positive value for one batch.
+ Anchor: `daemon-manual#max-turns`. Positive `LINGTAI_DAEMON_MAX_TURNS` overrides
+ explicit capability/setup `max_turns`, then `daemon/daemon.json`, then 5000.
+ Invalid file/env values fall back. `emanate.max_turns` narrows one batch only;
+ budget for exploration, action, and verification, not just the final edit.
### Manager pool size
- Anchor: `daemon-manual#manager-pool-size`. Current value and application belong
- to `daemon.settings`; precedence and rebuild details belong to the Contract.
+ Anchor: `daemon-manual#manager-pool-size`. Nonnegative
+ `LINGTAI_DAEMON_MANAGER_POOL_SIZE` overrides capability/setup `manager_pool_size`,
+ then `daemon/daemon.json`, then 100. Zero bypasses the central manager and uses per-run supervisors. Invalid file/env values fall back; this is not a per-run option.
### System prompt budget chars
- Anchor: `daemon-manual#system-prompt-budget-chars`. Current value and
- application belong to `daemon.settings`; prompt-budget behavior belongs to the
- Contract. SHOW does not mutate it.
+ Anchor: `daemon-manual#system-prompt-budget-chars`. Positive
+ `LINGTAI_DAEMON_SYSTEM_PROMPT_BUDGET_CHARS` overrides valid capability/setup
+ `system_prompt_budget_chars`, then `daemon/daemon.json`, then 20000. Invalid
+ values retain the previous valid layer. Oversized final prompts fail rather than
+ silently truncating the task; this character limit is not a context window.
### Timeout
- Anchor: `daemon-manual#timeout`. Current value and application belong to
- `daemon.settings`; precedence and failure behavior belong to the Contract.
- Per-call `emanate.timeout` is a one-batch override, not a settings mutation.
-
- ## Progress, inspection, and follow-up
-
- Every terminal outcome (`done`, `failed`, `cancelled`, `timeout`) is
- push-notified exactly once. Do not poll for "is it done". After notification,
- call `check` and open the durable `result.txt`/error path for full output;
- previews and notification text are bounded. `list` is a bounded ledger sweep,
- not a lifetime folder scan. `check` accepts a live id or exact historical run
- id and returns state, events, paths, and an artifact manifest. Read inspection
- before declaring a stall or reclaiming on a hunch.
-
- For large batches, use `group_id` for logical audit but each run id for filesystem
- identity. A Task Card is conditional on the dispatch handoff: use it only when
- Telegram is connected and a card exists; daemon itself creates no watcher.
-
- ## Compact and completion boundaries
-
- Every LingTai daemon receives intrinsic `compact`; external CLIs do not. Its
- `action` is required: `manual` is read-only, while `run` is a repeatable
- non-terminal reset. Call `compact(action="run", _reason="...")` as the sole
- assistant-batch tool call with a complete self-contained handoff. Never call the
- unavailable parent `system.summarize`.
-
- MCP-capable backends also receive built-in `daemon_common`. Call its
- `checkpoint` at useful nonterminal boundaries; it is not chat, cancellation,
- preemption, or completion. Before ending, call `finish` exactly once. Only
- `finish(status="done")` permits terminal success. Background-and-wait is
- invalid: run validation synchronously with an adequate explicit timeout and
- inspect the result in the same run. Missing/invalid completion is a failure;
- inspect durable artifacts before assuming anything was lost.
-
- ## Safety, Shell events, and footprint
-
- Keep the parent task's authorization and privacy boundary authoritative. Do not
- use daemon for durable identity, automatic recursion, or hidden context. A
- selected daemon `shell` has a private `<run>/shell-jobs` namespace and no parent
- notification store; read `shell-manual` for async + poll supervision. Do not
- reclaim on a hunch: it terminates work in flight but keeps run folders as
- evidence. There is no automatic cleanup.
-
- Inspection, forensics, dispatch-ledger, cleanup, shell-event, programmatic-use,
- and no-deletion routes remain available through the references above. Never
- permit deletion, global configuration/install changes, account/provider changes,
- or cleanup outside an authorized scope.
-
- ## Programmatic use / CLI
-
- For scripts and CI, the reusable boundary is
- `lingtai.services.daemon.DaemonService(state_root)`. It owns daemon artifacts
- under that existing caller-chosen directory and never constructs an Agent. A
- native LingTai task must carry its preset path directly; this mode never reads
- or requires `init.json`:
-
- ```python
- from lingtai.services.daemon import DaemonService
-
- service = DaemonService("/absolute/path/to/daemon-state")
- result = service.emanate([{
- "task": "Do the bounded task and leave reviewable artifacts.",
- "tools": ["file"],
- "preset": "/absolute/path/to/preset.json",
- }])
- snapshot = service.check(result["ids"][0])
- ```
-
- The CLI is only a driver over that object. Its state root and existing task
- payload are sufficient; there is no preview confirmation or Agent-directory
- compatibility path:
+ Anchor: `daemon-manual#timeout`. Manager watchdog seconds come only from
+ capability/setup `timeout` (default 3600.0), not the daemon JSON or an environment
+ key. `emanate.timeout` overrides one batch, not this manager setting.
- ```text
- lingtai-agent daemon emanate --state-root /absolute/state --tasks tasks.json
- lingtai-agent daemon check em-1234 --state-root /absolute/state
- ```
+ ## Routing table
- Use `lingtai-agent daemon --help` for exact options. External CLI backends keep
- the engine's existing no-preset mechanics; the direct-preset requirement is for
- native `lingtai` work.
+ | Concrete need | Read one direct owner |
+ |---|---|
+ | backend choice, aliases, CLI options, native MCP, async ask | `reference/cli-backends/SKILL.md` |
+ | native LingTai preset, skills, MCP, context, completion | `reference/cli-backends/reference/backends/lingtai/SKILL.md` |
+ | stalled run, 143/SIGTERM, result/transcript/token evidence | `reference/forensics/SKILL.md` |
+ | ledger warnings or identity mismatch | `reference/dispatch-ledger/SKILL.md` |
+ | reclaim footprint, consent, deletion boundary | `reference/cleanup/SKILL.md` |
+ | Shell async events | `shell-manual` |
+ | programmatic/CI driver | `lingtai-agent daemon --help` |
- ## Maintenance
+ ## Standalone boundary
- Keep this file a router. Put backend command recipes and reserved flags in the
- per-backend references; keep inspection, forensics, ledger, shell, and cleanup
- procedures there. Keep the action and settings anchors stable as deeper owners
- move.
+ `DaemonService(state_root)` is not an Agent and owns no Agent lease, prompt,
+ identity, lifecycle, or manager-control authority. Native standalone LingTai
+ tasks require a directly loadable preset; external CLIs retain no-preset
+ mechanics. Daemon capability does not authorize software installation, credential changes,
+ evidence deletion, or other work beyond the approved scope. `reclaim` stops work but does not clean
+ folders; molt clears conversation context and does not wipe durable stores or
+ daemon run folders.