Scout reads settings from environment variables and loads a local .env file.
Copy .env.example for a complete template.
| Variable | Default | Description |
|---|---|---|
RELEVANCE_THRESHOLD |
0.7 |
Minimum score included in a digest |
SCAN_INTERVAL_HOURS |
6 |
Delay between continuous-mode scans |
MAX_MESSAGES_PER_CHANNEL |
200 |
Maximum messages fetched per channel and scan |
SCAN_MAX_NEW_MESSAGES |
300 |
Maximum new messages evaluated after fetch and deduplication; 0 disables the cap |
KEYWORD_PREFILTER |
true |
Drop messages that do not match project keywords before model evaluation |
SCOUT_ENVIRONMENT |
development |
Provenance label: development, test, or production |
DB_PATH |
scout.db |
Scout state database |
TRACE_DB_PATH |
scout_traces.db |
Jig trace database |
FEEDBACK_DB_PATH |
scout_feedback.db |
Jig feedback database |
| Variable | Default | Description |
|---|---|---|
TYPESAFE_SHADOW_MODE |
false |
Run the non-gating shadow relevance node for agent-ops routes |
TYPESAFE_SHADOW_BACKEND |
placeholder |
Shadow backend; only placeholder is registered in this release |
TYPESAFE_API_KEY |
unset/off | Placeholder for the remote backend; unused until the backend cohort lands |
TYPESAFE_CATALOGUE_PATH |
packaged agent-ops-relevance.v0-fixture.yaml |
Validated catalogue YAML path |
TYPESAFE_PLACEHOLDER_ANSWERS_PATH |
unset | Placeholder answer fixture path; required when shadow mode is enabled |
The offline fitter accepts an inline RelevanceTask JSON document (or a path
to one), one catalogue version, and operator-selected false-positive and
false-negative costs:
uv run scout typesafe fit \
--task relevance-task.json \
--catalogue-version <sha256> \
--c-fp 1 --c-fn 1 \
--out evidence/shadow-relevance-2026-09-17/
Only a task with partition: "train" and a retained partition_digest is
accepted. The command refuses all and heldout before opening the database,
then loads and verifies the FrozenPartition before querying training rows.
The report command’s --since cutoff is inclusive and requires an ISO-8601
timestamp with an explicit Z or numeric timezone offset; date-only and
timezone-naive values are rejected.
It writes weight-set.json, PLAN.md, RESULTS.md, checksums.json, and
inventory.json. The default costs are both 1; their ratio determines the
decision threshold and uncertainty band and both values are retained in the
weight set. The pinned September agent-ops task is partition: "all" with no
digest, so it cannot be fitted until the label-packet work pins a partition.
With the default symmetric costs (c_fp = c_fn = 1), the threshold is 0.5
and the uncertainty band is the single point [0.5, 0.5]; only a prediction
of exactly 0.5 is marked uncertain. Operators who require a wider uncertainty
zone must choose asymmetric costs or define a different policy in a future
version rather than assuming the defaults create a margin around the threshold.
| Variable | Default | Description |
|---|---|---|
FARCASTER_MAX_RESULTS_PER_QUERY |
25 |
Results fetched per search or channel request |
FARCASTER_MAX_PAGES |
10 |
Page ceiling per Farcaster request stream |
BLUESKY_MAX_RESULTS_PER_QUERY |
25 |
Results fetched per search or feed request |
BLUESKY_MAX_PAGES |
10 |
Page ceiling per Bluesky request stream |
BLUESKY_LANGS |
unset | Comma-separated language tags; missing post language metadata is retained |
Bluesky runs every built query against every configured language. Its maximum keyword-search page count per scan is:
number of queries × max(1, number of languages) × BLUESKY_MAX_PAGES
Each configured BLUESKY_FEED_URIS entry adds another paginated request
stream. Adding keywords or languages therefore increases rate-limit exposure
multiplicatively.
| Variable | Default | Description |
|---|---|---|
SCOUT_LEASE_TTL_SECONDS |
120 |
TTL a canonical live owner’s environment lease is granted for on acquire, and extended to on each heartbeat renewal |
SCOUT_LEASE_HEARTBEAT_SECONDS |
30 |
Interval between heartbeat renewals; must leave room for at least 2 missed heartbeats within SCOUT_LEASE_TTL_SECONDS |
SCOUT_RECOVERY_LOCK_TTL_SECONDS |
1800 |
TTL of the exclusive recovery lock scout watermark probe/backfill/cutover hold for one operator invocation |
SCOUT_CUTOVER_PROBE_MAX_AGE_SECONDS |
3600 |
How recent a passed six-hour probe must be to gate a controlled cutover |
SCOUT_BACKFILL_MAX_PAGES_PER_SOURCE |
20 |
Bounded-backfill page ceiling per source |
SCOUT_STALE_WATERMARK_HOURS |
24 |
A canonical live watermark older than this is reported stale by scout watermark stale-check |
See docs/runbooks/watermark-recovery.md for the operational procedure
these gate — probe, bounded backfill, and controlled cutover.
| Variable | Default | Description |
|---|---|---|
LLM_MODEL |
claude-sonnet-4-6 |
Backward-compatible default for all phases |
RELEVANCE_MODEL |
LLM_MODEL |
High-volume relevance triage |
REPLY_DRAFT_MODEL |
LLM_MODEL |
Reply drafting |
CRITIC_MODEL |
LLM_MODEL |
Critique, rejection, and revision |
Model names pass directly to jig.from_model; Jig selects the backend from
the prefix:
claude-* uses Anthropic and requires ANTHROPIC_API_KEY.openrouter/<vendor>/<slug> uses OpenRouter and requires
OPENROUTER_API_KEY.dispatch/<name> uses the service configured by DISPATCH_URL.ollama/<name> uses a local Ollama server.Preflight resolves model identity separately from routing. Its default pipeline-wide requirement remains at least two distinct recognized model families across relevance, reply drafting, and critique. This is a diversity check, not proof of evaluator independence or a worker–critic-specific qualification gate.
Recognized OpenRouter namespace/family pairs are anthropic/claude-*,
openai/gpt-* (also chatgpt-*), openai/o1, openai/o3, openai/o4
(including their hyphenated variants, grouped as o-series),
google/gemini-*, moonshotai/kimi-*, and qwen/qwen* (numeric or hyphenated
version suffixes). For example, the published identifiers for
Kimi K2 and
Qwen3 become
openrouter/moonshotai/kimi-k2 and openrouter/qwen/qwen3-235b-a22b in Jig.
Direct Claude, GPT/ChatGPT, o-series, and Gemini identifiers resolve to the same families as their OpenRouter counterparts. A different route, version, or model size does not create another family. Recognition does not check API availability, credentials, pricing, or behavioral qualification, and does not change the models configured for any phase.
Unknown identifiers and undeclared Dispatch or Ollama aliases fail preflight with a diagnostic rather than count as another family. Custom identities and the task’s diversity requirement belong in deployment-local configuration, not in the shared built-in registry or the public repository.
Set SCOUT_MODEL_IDENTITY_CONFIG in the ignored local .env file to a JSON
object with this shape (example metadata, not an active model selection):
{
"policy": {"minimum_families": 2},
"identities": [
{"model": "dispatch/reviewer", "developer": "moonshotai", "family": "kimi"},
{"model": "ollama/local-drafter", "developer": "qwen", "family": "qwen"}
]
}
Store that JSON on one line in .env. When the variable is unset, the policy
defaults to two families with no custom declarations. policy and identities
can each be omitted. minimum_families must be an integer from 1 to 3 for the
three configured phases. Setting it to 1 is an explicit operator policy change;
it still requires every configured model identity to resolve. No deployment
policy or model selection changes merely by installing this code.
Declarations match exact identifiers, without wildcard or prefix matching. They supply identity metadata, not routing overrides: Jig still routes using the original identifier. Use canonical built-in family/developer names when an alias serves a known family. A new developer/family can be declared locally for a Dispatch/Ollama alias or an unknown OpenRouter slug in its matching namespace. The operator is responsible for keeping alias metadata consistent with what the backend actually serves; preflight cannot verify that claim. Duplicate entries, malformed settings, unknown fields, unsupported routes, and declarations that contradict built-in identities fail preflight, including unused declarations. Developer/family labels use lowercase letters, digits, dots, underscores, or hyphens, starting with a letter or digit.
The report retains model_families and adds model_identities containing the
exact configured identifier, route, developer namespace, family, and whether the
identity is built-in or locally declared. model_diversity_policy prints the
effective requirement. These diagnostics may contain private alias names and
must be reviewed before publication. This remains a pipeline-wide preflight
policy, not a new worker–critic-specific rule or an autonomy declaration change.
With keyword prefiltering enabled, a scan of 200 messages might send 10–30 to the agent. Each candidate normally takes one or two model turns. Actual cost depends on message length, dossier context, model choice, and provider pricing; use provider usage reporting rather than treating a fixed estimate as a budget.
Security-sensitive sidecar and web settings are documented separately in Deployment security.