Skip to content

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:

  1. A keyword argument to KyvvuSettings(...), KyvvuRunner(...) or Kyvvu(...).
  2. An environment variable that is already exported in the process.
  3. A .env file in the current working directory.
  4. 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

  • .env is read from the current working directory, once, when kyvvu (or kyvvu_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 and kyvvu init scaffolds 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 .env edited after the process has started is not re-read.
  • The parser is deliberately small: one KEY=VALUE per line, # only at the start of a line, matching quotes around the value removed. export KEY=value does not work (the variable is stored under the name export KEY, so KEY stays unset), and a trailing comment becomes part of the value (KV_AGENT_KEY=my-agent # prod sets the key to my-agent # prod). Put comments on their own line and leave export out of the file.
  • Relative paths are relative to the working directory, not to the .env. KV_POLICY_FILE=demo-manifest.yml and a file KV_LOG_LOCATION resolve against where you run the command.
  • kyvvu try and kyvvu serve --policy-file read KV_ENVIRONMENT from the same places; they pin their policy source and credentials rather than reading them.
  • The kyvvu command 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:

  1. The platform, when KV_API_URL, KV_API_KEY and KV_AGENT_KEY are all set.
  2. A local set: an inline policies= list, or the manifest path(s) in KV_POLICY_FILE, comma-separated, loaded with no credentials and no network. A local set is re-read once per KV_POLICY_TTL_SECONDS.
  3. 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.