Engine settings¶
Every setting the engine reads, the KV_* environment variable that sets it, and its
default. The table at the end of this page is generated from the KyvvuSettings
declarations, so it is the only place a default is stated. The guidance before it explains
how the engine chooses a value.
Precedence¶
Each setting takes the first value it finds, highest first:
- A keyword argument to
KyvvuSettings(...),KyvvuRunner(...)orKyvvu(...). - An environment variable that is already exported in the process.
- A
.envfile in the current working directory. - The built-in default in the table.
Set KV_ENVIRONMENT=development for local work: a run that sets nothing registers its
agent in the environment the table shows, and environment-specific policies behave
accordingly. kyvvu init scaffolds the variable in .env.example, and kyvvu try prints
the environment it evaluated as.
How .env is read¶
.envis read from the current working directory, once, whenkyvvu(orkyvvu_engine) is first imported. It is not searched for in parent directories and not relative to your script: start the program from another directory and the file is silently not found. Run from the directory that holds it (the demo andkyvvu initscaffolds assume so), or export the variables.- A variable that is already exported wins over the same name in
.env, which only fills in what is missing. A.envedited after the process has started is not re-read. - The parser is deliberately small: one
KEY=VALUEper line,#only at the start of a line, matching quotes around the value removed.export KEY=valuedoes not work (the variable is stored under the nameexport KEY, soKEYstays unset), and a trailing comment becomes part of the value (KV_AGENT_KEY=my-agent # prodsets the key tomy-agent # prod). Put comments on their own line and leaveexportout of the file. - Relative paths are relative to the working directory, not to the
.env.KV_POLICY_FILE=demo-manifest.ymland a fileKV_LOG_LOCATIONresolve against where you run the command. kyvvu tryandkyvvu serve --policy-filereadKV_ENVIRONMENTfrom the same places; they pin their policy source and credentials rather than reading them.- The
kyvvucommand line also has a configuration file of its own, described in the CLI reference. The engine does not read it.
Policy source¶
The engine enforces the policy set of exactly one policy source. The first one that is fully configured wins:
- The platform, when
KV_API_URL,KV_API_KEYandKV_AGENT_KEYare all set. - A local set: an inline
policies=list, or the manifest path(s) inKV_POLICY_FILE, comma-separated, loaded with no credentials and no network. A local set is re-read once perKV_POLICY_TTL_SECONDS. - The disk cache at
KV_POLICY_CACHE_PATH, written after each successful fetch from the platform.
A manifest left on a credentialed host cannot displace the organization's policy set: when
the credentials and KV_POLICY_FILE are all only in the environment, the platform wins. The
one exception follows from the precedence above: a policy_file= or policies= passed by
name to KyvvuRunner outranks credentials that were only in the environment. With none of
the three configured, the runner refuses to be built.
If a local file cannot be read when it is the only source, the runner refuses to be
constructed, and a server exits rather than booting ungoverned. When there is a fallback (an
inline set, a disk cache, or a set from an earlier good load), that fallback is used,
load_state reports stale_cache rather than enforcing, and one line naming the path
goes to stderr. A broken manifest is never silently substituted for a working one. The disk
cache is used even when it is older than KV_POLICY_CACHE_MAX_AGE_SECONDS; that age only
adds a staleness warning.
Fail mode¶
KV_POLICY_FAIL_MODE decides what happens to an action step when no policy set can be
loaded at all. In the closed fail mode the step is blocked; in the open fail mode it is
allowed. Task-boundary markers and an empty assigned set are allowed in either mode, because
neither is a missing policy.
Clock skew¶
KV_MAX_CLOCK_SKEW_SECONDS bounds how far, in either direction, a behaviour's timestamp
may be from this host's UTC clock for KyvvuRunner.evaluate() to accept it; /evaluate on
kyvvu serve answers 422 outside it. The value must be positive: zero and negative values
are refused when the settings are built, and there is no unbounded value.
Time-based rules such as working_hours_only evaluate against the behaviour's own
timestamp, which the client records when the intent is formed, not against a separate
evaluation time; EvalContext has no now field. So a preflight is judged at the time the
intent was formed, even when the action waits behind a slow human gate before it executes.
The clock skew bound applies only to that live entrance: record(), restore_task(),
restore_intent() and a PolicyEngine used directly replay recorded history and accept any
timestamp.
Settings¶
The Default column shows each environment default as the source string, before conversion
to the declared type. None means unset.
| Setting | Type | Environment | Default | Meaning |
|---|---|---|---|---|
api_url |
str |
KV_API_URL |
'https://platform.kyvvu.com' |
Base URL of the Kyvvu API. |
api_key |
str \| None |
KV_API_KEY |
None |
Bearer API key for authentication. |
agent_key |
str \| None |
KV_AGENT_KEY |
None |
Agent key used to fetch agent-specific policies. |
declared_tools |
list[str] \| None |
KV_DECLARED_TOOLS |
'' |
Tool names allowed for this agent's steps. Defaults to the comma-separated KV_DECLARED_TOOLS environment variable. |
incident_location |
str \| None |
KV_INCIDENT_LOCATION |
None |
WHERE incidents go (same vocabulary as log_location). None inherits the trace sink location (with the …/api/v1/incidents kv path substituted for …/api/v1/logs/batch). See effective_incident_location. |
incident_format |
str \| None |
KV_INCIDENT_FORMAT |
None |
HOW incidents are formatted ("kv", "json", "otlp"). None inherits the trace format (log_format). |
instance_id |
str \| None |
KV_INSTANCE_ID |
None |
Human-readable instance prefix. A random suffix is appended at each runner construction, so the instance id is not stable across restarts and is not an identity. None generates a UUID4. |
log_payloads |
str |
KV_LOG_PAYLOADS |
'full' |
"full" or "metadata_only". Controls whether batch log payloads include raw input/output or redacted metadata. |
environment |
str |
KV_ENVIRONMENT |
'production' |
Deployment environment label forwarded to EvalContext. |
policy_ttl_seconds |
int |
KV_POLICY_TTL_SECONDS |
'300' |
Seconds before the policy cache is refreshed. |
registration_ttl |
float \| None |
KV_REGISTRATION_TTL |
None |
Seconds before a registration cache entry expires, or None for no expiry. |
http_timeout_seconds |
int |
KV_HTTP_TIMEOUT_SECONDS |
'10' |
Per-request HTTP timeout in seconds. |
report_queue_size |
int |
KV_REPORT_QUEUE_SIZE |
'1000' |
Bound of the outbound report queue (incidents and trace flushes). Overflow drops and counts. Default: 1000. |
report_exit_flush_seconds |
float |
KV_REPORT_EXIT_FLUSH_SECONDS |
'2' |
Deadline for the atexit flush of queued reports. Default: 2. |
task_max_age_seconds |
int |
KV_TASK_MAX_AGE_SECONDS |
'3600' |
Seconds before an abandoned task buffer is evicted by sweep_stale_tasks(). Default: 3600. |
sweep_interval_seconds |
int |
KV_SWEEP_INTERVAL_SECONDS |
'300' |
How often the background sweeper runs (in seconds). Default: 300 (5 minutes). |
sweep_enabled |
bool |
KV_SWEEP_ENABLED |
'true' |
Whether the background sweeper thread is started automatically. Default: True. Set to False for tests or deployments that call sweep_stale_tasks() manually. The runner warns that task memory is unbounded when this is off, except when it is named in explicit_fields (passed as a KyvvuRunner keyword), which marks it deliberate. |
sweep_flush_on_evict |
bool |
KV_SWEEP_FLUSH_ON_EVICT |
'true' |
Whether to attempt a batch log post for evicted tasks before discarding their buffers. Default: True. |
max_clock_skew_seconds |
int |
KV_MAX_CLOCK_SKEW_SECONDS |
'300' |
How far a behaviour's timestamp may be from the host clock, in either direction, for KyvvuRunner.evaluate() to accept it. Replay paths are not bounded. Must be positive. Default: 300. |
log_level |
str |
KV_LOG_LEVEL |
'INFO' |
Python log level name for kyvvu / kyvvu_engine loggers. Applied when the settings object is instantiated. Default: "INFO". |
fail_mode |
str |
KV_POLICY_FAIL_MODE |
'closed' |
"closed" (default) or "open". When policies are unavailable, closed blocks action steps; open allows them. Task-boundary markers and an empty policy set are allowed. |
policies |
list[dict[str, Any]] \| None |
None |
An inline policy set, in the shape load_policies() takes. Keyword-only in practice: there is no KV_* variable for it, because a policy set is not an environment-variable-shaped value. None means "not a source"; an explicitly empty list is a source that offers nothing, which loads as none_configured rather than being silently ignored. |
|
policy_file |
str |
KV_POLICY_FILE |
'' |
One or more manifest YAML paths, comma-separated, loaded as the policy source with no credentials and no network. |
policy_cache_path |
str |
KV_POLICY_CACHE_PATH |
'' |
File path for on-disk policy cache. Empty string disables disk caching. |
policy_cache_max_age_seconds |
int |
KV_POLICY_CACHE_MAX_AGE_SECONDS |
'86400' |
Maximum age of the on-disk cache before a staleness warning is emitted. Default: 86400 (24h). |
log_location |
str \| None |
KV_LOG_LOCATION |
'auto' |
WHERE logs go. URL → HTTP POST, file path → JSONL, "stdout" → print, "none"/"" → disabled, "auto" → the platform when it is the policy source, else "stdout" (see effective_log_location()). Default: "auto". |
log_format |
str |
KV_LOG_FORMAT |
'kv' |
HOW logs are formatted: "kv" (default), "json", or "otlp". |
template_location |
str \| None |
KV_TEMPLATE_LOCATION |
None |
Custom behavior template path, or None to use each integration's packaged template. |