Configuration Reference
Complete reference for AgentVisor™ configuration options.
Every setting is available both as a YAML key in agentvisor.yaml and as an AGENTVISOR_*
environment variable. Environment variables take precedence over the config file.
Env var convention: take the YAML key, uppercase it, replace dots with underscores, and prefix
with AGENTVISOR_. For example, temporal.target → AGENTVISOR_TEMPORAL_TARGET. Every env var
appears in its concept section alongside the YAML key, default, and description — use your
browser's Find (⌘F / Ctrl+F) to locate any variable by name.
Configuration Sources
Configuration is read from (in order of precedence, later wins):
- Default values (built-in)
- Base config file (
agentvisor.yaml) conf.d/drop-in fragments (alphabetically sorted, adjacent to base config)- Overlay files (
--configflags orAGENTVISOR_CONFIG_FILES) - Environment variables (highest precedence)
The root-level file-loading variables are:
| Variable | Description |
|---|---|
AGENTVISOR_CONFIG | Path to base config file (overrides default search paths) |
AGENTVISOR_CONFIG_FILES | Comma-separated overlay config files merged on top of base config |
See Config File Locations and Multi-Config Files for layering details.
Logging
AgentVisor uses a unified structured logging pipeline. All components — host, guest runtime, Temporal SDK, and agent logs — share the same output sink and format.
| Env var | Description |
|---|---|
AGENTVISOR_LOGGING_FORMAT | Log format: plain (human-readable) or json (structured) |
AGENTVISOR_LOGGING_LEVEL | Log level grammar: \\<global\\>[,\\<component\\>=\\<level\\>]* (e.g. warn,agent=debug,temporal=error); components: host, guest, temporal, agent |
AGENTVISOR_LOGGING_OUTPUT | Log destination: empty/stderr, stdout, discard, /path/to/file, or rotate:/path/to/file |
logging:
format: "plain"
level: "info"
output: ""
rotation:
compress: false
max_age_days: 28
max_backups: 3
max_size_mb: 100
Log Level Grammar
logging.level accepts a grammar string with optional per-component overrides:
<global>[,<component>=<level>]*
| Form | Example | Effect |
|---|---|---|
| Simple | info | All components at info |
| With override | warn,agent=debug | Host/guest/temporal at warn; agent at debug |
| Multiple overrides | warn,agent=debug,temporal=error | Mixed levels |
Valid levels: trace, debug, info, warn, warning, error (case-insensitive).
Known components: host, guest, temporal, agent, mcp, a2a.
Components may have dot-separated sub-components (e.g. host.accesslog,
mcp.client, mcp.pool, a2a.client, a2a.pool). An override matches the
longest dot-boundary prefix of the logger name: given overrides for both
host and host.accesslog, a log line from host.accesslog uses the
host.accesslog level and a log line from host.grpc falls back to the
host level. A component with no matching override (exact or prefix) falls
back to the global level. mcp=warn,mcp.pool=debug is valid — it quiets the
mcp umbrella while raising the connection pool sub-component to debug.
An override key that doesn't resolve to a known component — neither exactly
nor as a dot-boundary descendant of one — parses without error but has no
effect at runtime (there is no logger by that name to match); Setup logs a
startup warning naming the unrecognized key rather than failing, since a typo
here should never abort startup.
Guest Agent RPC Audit Logging
| Variable | Default | Description |
|---|---|---|
AGENTVISOR_GUEST_AGENT_RPC_LOG_LEVEL | summary | AgentService gRPC call audit logging: none, summary, full |
Examples
# Debug all components
AGENTVISOR_LOG_LEVEL=debug agentvisor serve ./my-agent
# Quiet Temporal SDK while keeping everything else at debug
AGENTVISOR_LOG_LEVEL=debug,temporal=warn agentvisor serve ./my-agent
# Debug agent code only
AGENTVISOR_LOG_LEVEL=warn,agent=debug agentvisor serve ./my-agent
- Agent not starting?
AGENTVISOR_LOG_LEVEL=debug - Agent logic issues?
AGENTVISOR_LOG_LEVEL=warn,agent=debug - Unexpected API behavior?
AGENTVISOR_GUEST_AGENT_RPC_LOG_LEVEL=full - Temporal SDK noise?
AGENTVISOR_LOG_LEVEL=debug,temporal=warn
Deprecated Fields
| Deprecated env var | Replacement |
|---|---|
AGENTVISOR_LOG_LEVEL | AGENTVISOR_LOGGING_LEVEL |
AGENTVISOR_LOG_FORMAT | AGENTVISOR_LOGGING_FORMAT |
Temporal
Connect AgentVisor to a Temporal server (local or Temporal Cloud).
| Env var | Description |
|---|---|
AGENTVISOR_TEMPORAL_CAN_PAYLOAD_BUDGET_BYTES | Advanced override (0 = auto, derived from max_checkpoint_bytes): threshold a thread's estimated Continue-As-New payload (checkpoint data/state plus any pending writes) must stay under for pending writes to be retained rather than dropped on a CAN. Pinned into a thread's config at creation — raising it only benefits threads created afterward |
AGENTVISOR_TEMPORAL_FORCE_CONTINUE_AS_NEW_AFTER_RUNS | Force Continue-As-New after this many run completions per workflow execution (0 = disabled) |
AGENTVISOR_TEMPORAL_FORCE_CONTINUE_AS_NEW_DURING_ACTIVE_RUN | Force Continue-As-New while a run is actively executing (testing only; a thread's whole Continue-As-New chain is pinned to whichever value was in effect when the thread was first created — enabling or disabling this later only affects threads created afterward; see the Temporal guide for the transient interrupted response this causes) |
AGENTVISOR_TEMPORAL_LOG_LEVEL | Temporal SDK log level override (empty = inherit from global logging.level) |
AGENTVISOR_TEMPORAL_MAX_CHECKPOINT_BYTES | The largest single checkpoint an agent may write — state + metadata + channel_values combined (0 = automatic: 1MiB with checkpoint storage disabled, 8MiB with it enabled). Every other pending-writes size knob derives from this one unless explicitly overridden. Pinned into a thread's config at creation — raising it only benefits threads created afterward |
AGENTVISOR_TEMPORAL_MAX_CHECKPOINT_HISTORY | Maximum number of checkpoints retained per run (older ones pruned) |
AGENTVISOR_TEMPORAL_MAX_PUT_WRITES_PER_EXECUTION | Force Continue-As-New after this many put_writes Update calls per workflow execution (0 = disabled); bounds LangGraph checkpoint-write-driven history growth proactively instead of relying solely on Temporal's own history-size CAN suggestion |
AGENTVISOR_TEMPORAL_MAX_RUN_HISTORY | Maximum number of runs retained per thread workflow (older ones pruned on Continue-As-New) |
AGENTVISOR_TEMPORAL_NAMESPACE | Temporal namespace |
AGENTVISOR_TEMPORAL_PENDING_WRITE_VALUE_MAX_SIZE | Maximum size in bytes of a single LangGraph pending write's value (0 = auto, derived from max_checkpoint_bytes; oversized writes are dropped, not errored). Pinned into a thread's config at creation and enforced by the guest's own per-write validator — raising it only benefits threads created afterward |
AGENTVISOR_TEMPORAL_PENDING_WRITES_ENABLED | Persist LangGraph's mid-superstep pending writes (put_writes) (a thread's whole Continue-As-New chain is pinned to whichever value was in effect when the thread was first created — enabling or disabling this later only affects threads created afterward) |
AGENTVISOR_TEMPORAL_PENDING_WRITES_MAX_PER_CHECKPOINT | Maximum number of distinct pending writes retained per checkpoint (excess writes are dropped, not errored). A fixed guest-side validator constant additionally caps every request at 256 writes — this setting can only lower that effective limit, never raise it |
AGENTVISOR_TEMPORAL_PENDING_WRITES_TOTAL_BYTES | Advanced override (0 = auto, derived from max_checkpoint_bytes and can_payload_budget_bytes): maximum total size in bytes across all pending writes retained against a single checkpoint (excess writes are dropped, not errored), both at Continue-As-New time and at write time |
AGENTVISOR_TEMPORAL_STATE_KEY_MAX_SIZE | Maximum size in bytes of a single thread state key |
AGENTVISOR_TEMPORAL_STATE_MAX_KEYS | Maximum number of keys in thread state |
AGENTVISOR_TEMPORAL_STATE_TOTAL_MAX | Maximum total size in bytes of all thread state values combined |
AGENTVISOR_TEMPORAL_STATE_VAL_MAX_SIZE | Maximum size in bytes of a single thread state value |
AGENTVISOR_TEMPORAL_TARGET | Temporal server address (e.g. localhost:7233 or my-ns.account.tmprl.cloud:7233) |
AGENTVISOR_TEMPORAL_TASK_QUEUE | Temporal task queue name |
temporal:
can_payload_budget_bytes: 0
force_continue_as_new_after_runs: 0
force_continue_as_new_during_active_run: false
log_level: ""
max_checkpoint_bytes: 0
max_checkpoint_history: 1
max_put_writes_per_execution: 0
max_run_history: 100
namespace: "default"
pending_write_value_max_size: 0
pending_writes_enabled: true
pending_writes_max_per_checkpoint: 256
pending_writes_total_bytes: 0
state_key_max_size: 1024
state_max_keys: 10000
state_total_max: 10485760
state_val_max_size: 1048576
target: "localhost:7233"
task_queue: "agentvisor"
Temporal Cloud Authentication
For connecting to Temporal Cloud, AgentVisor supports API Key and mTLS authentication.
| Env var | Description |
|---|---|
AGENTVISOR_TEMPORAL_AUTH_API_KEY | Temporal Cloud API key — set via AGENTVISOR_TEMPORAL_AUTH_API_KEY env var |
AGENTVISOR_TEMPORAL_AUTH_TYPE | Temporal Cloud authentication: api_key, mtls, or empty (local Temporal) |
AGENTVISOR_TEMPORAL_AUTH_MTLS_CA_DATA | Base64-encoded custom CA certificate for verifying the Temporal Cloud server (alternative to ca_file) |
AGENTVISOR_TEMPORAL_AUTH_MTLS_CA_FILE | Path to custom CA certificate for verifying the Temporal Cloud server |
AGENTVISOR_TEMPORAL_AUTH_MTLS_CERT_DATA | Base64-encoded mTLS client certificate (alternative to cert_file) |
AGENTVISOR_TEMPORAL_AUTH_MTLS_CERT_FILE | Path to mTLS client certificate file |
AGENTVISOR_TEMPORAL_AUTH_MTLS_KEY_DATA | Base64-encoded mTLS client private key (alternative to key_file) |
AGENTVISOR_TEMPORAL_AUTH_MTLS_KEY_FILE | Path to mTLS client private key file |
AGENTVISOR_TEMPORAL_AUTH_MTLS_SERVER_NAME | TLS SNI server name override for the Temporal Cloud connection |
temporal:
auth:
api_key: ""
mtls:
ca_data: ""
ca_file: ""
cert_data: ""
cert_file: ""
key_data: ""
key_file: ""
server_name: ""
type: ""
Example — API Key:
temporal:
target: my-namespace.account-id.tmprl.cloud:7233
namespace: my-namespace.account-id
auth:
type: api_key
# Set via AGENTVISOR_TEMPORAL_AUTH_API_KEY — do not put in YAML
Example — mTLS:
temporal:
target: my-namespace.account-id.tmprl.cloud:7233
namespace: my-namespace.account-id
auth:
type: mtls
mtls:
cert_file: /etc/temporal/client.crt
key_file: /etc/temporal/client.key
See the Temporal Configuration Guide for setup instructions.
Encryption at Rest
AgentVisor supports encrypting Temporal workflow payloads at rest using a pluggable codec.
| Env var | Description |
|---|---|
AGENTVISOR_TEMPORAL_CODEC_ENABLED | Enable payload encryption for Temporal workflows (encryption at rest) |
AGENTVISOR_TEMPORAL_CODEC_TYPE | Payload codec provider (e.g. aes256); required when enabled: true |
AGENTVISOR_TEMPORAL_CODEC_SERVER_ALLOWED_ORIGINS | CORS origins allowed to access the codec server (required for Temporal Web UI) |
AGENTVISOR_TEMPORAL_CODEC_SERVER_ENABLED | Enable the HTTP codec server for Temporal Web UI payload decryption |
AGENTVISOR_TEMPORAL_CODEC_SERVER_LISTEN_ADDR | Listen address for the HTTP codec server (loopback by default) |
AGENTVISOR_TEMPORAL_CODEC_SERVER_MAX_BODY_SIZE | Maximum request body size in bytes for the codec server's /encode and /decode endpoints |
AGENTVISOR_TEMPORAL_CODEC_SERVER_AUTH_ALLOW_CREDENTIALS | Set Access-Control-Allow-Credentials, enabling the Web UI's cookie-based auth mode |
AGENTVISOR_TEMPORAL_CODEC_SERVER_AUTH_ENABLED | Require a valid Bearer token on /encode and /decode — without this, /decode is an unauthenticated decryption oracle |
AGENTVISOR_TEMPORAL_CODEC_SERVER_AUTH_OIDC_ALLOW_INSECURE | Permit plaintext http:// OIDC endpoints for the codec server — never enable in production (loopback hosts are always permitted) |
AGENTVISOR_TEMPORAL_CODEC_SERVER_AUTH_OIDC_AUDIENCE | Expected OIDC aud claim for the codec server's token validation |
AGENTVISOR_TEMPORAL_CODEC_SERVER_AUTH_OIDC_ISSUER | OIDC issuer used to validate the Bearer token the Temporal Web UI forwards |
AGENTVISOR_TEMPORAL_CODEC_SERVER_AUTH_OIDC_JWKS_URL | Override JWKS URL for codec server auth (must be https; use when discovered URL is not reachable, e.g. inside K8s) |
temporal:
codec:
enabled: false
server:
allowed_origins: []
auth:
allow_credentials: false
enabled: false
oidc_allow_insecure: false
oidc_audience: ""
oidc_issuer: ""
oidc_jwks_url: ""
enabled: false
listen_addr: "127.0.0.1:8091"
max_body_size: 10485760
type: ""
AES-256 Provider
The aes256 provider uses AES-256-GCM with PBKDF2 key derivation. Provider-specific options are
set via env vars namespaced by provider type:
| Variable | Default | Description |
|---|---|---|
AGENTVISOR_TEMPORAL_CODEC_AES256_PASSWORD | - | Encryption password (required) |
AGENTVISOR_TEMPORAL_CODEC_AES256_SALT | - | PBKDF2 salt, unique per deployment (required) |
AGENTVISOR_TEMPORAL_CODEC_AES256_ITERATIONS | 600000 | PBKDF2 iteration count (OWASP minimum; rejected below 100,000) |
Or via YAML config file:
temporal:
codec:
enabled: true
type: aes256
aes256:
# password is not set here: config loading does not expand ${VAR}
# syntax, so a value like "${CODEC_PASSWORD}" would become the literal
# password. Set AGENTVISOR_TEMPORAL_CODEC_AES256_PASSWORD instead.
salt: "unique-deployment-salt"
iterations: 600000
server:
enabled: true
listen_addr: "127.0.0.1:8091"
allowed_origins:
- "http://localhost:8080"
auth:
enabled: true
oidc_issuer: "https://idp.example.com"
oidc_audience: "agentvisor-codec"
- Password: Store in a secrets manager, not in the config file.
- Salt: Required. Must be unique per deployment — startup fails without one, to prevent rainbow table attacks against a shared value.
- Iterations: 600,000 is the OWASP-recommended minimum for PBKDF2-HMAC-SHA256; values below 100,000 are rejected at startup.
/decodeis a decryption oracle: it has no authentication untilauth.enabledis set.listen_addrdefaults to loopback for this reason — see Codec Server for Temporal Web UI before widening it or adding an off-hostallowed_originsentry.
Automatic Run Restart
When a run's agent invocation fails due to an infrastructure fault (heartbeat timeout,
worker loss, guest sandbox unavailable) or a guest/agent-process crash (signal-killed
exit, e.g. OOM/SEGV), AgentVisor can automatically restart it from the last checkpoint
with exponential backoff, bounded by an attempt budget and a wall-clock ceiling.
Agent-raised exceptions, cancellation, and interrupt() are never restarted.
| Env var | Description |
|---|---|
AGENTVISOR_TEMPORAL_RUN_RESTART_FORCE_FAILURE_CLASS | Test-only: force InvokeRun to synthesize a classified failure (CRASH or INFRA) on a run's first attempt only, bypassing the real guest client entirely (empty = disabled). Rejected by config validation when env: production |
AGENTVISOR_TEMPORAL_RUN_RESTART_INITIAL_INTERVAL | Backoff before the first restart attempt of a crashed/infra-failed run; doubles each subsequent attempt, capped at max_interval |
AGENTVISOR_TEMPORAL_RUN_RESTART_MAX_ATTEMPTS | Number of restart attempts allowed after the initial InvokeRun invocation for a run that fails with an infrastructure or guest/agent-process crash error (never agent-raised errors, cancellation, or interrupt()); 0 disables restart entirely |
AGENTVISOR_TEMPORAL_RUN_RESTART_MAX_ELAPSED | Total wall-clock time allowed across all restart attempts for a single run, checked between attempts |
AGENTVISOR_TEMPORAL_RUN_RESTART_MAX_INTERVAL | Cap on the exponential backoff between restart attempts |
AGENTVISOR_TEMPORAL_RUN_RESTART_REQUIRE_PROGRESS | Stop restarting early if a crash repeats with no checkpoint progress since the previous attempt, instead of exhausting the full attempt budget on a crash that will keep reproducing identically (always allows at least one restart regardless) |
temporal:
run_restart:
force_failure_class: ""
initial_interval: "2s"
max_attempts: 3
max_elapsed: "10m"
max_interval: "30s"
require_progress: true
Set max_attempts: 0 to disable restart entirely — a restartable failure then surfaces
as a run error on the first attempt, identical to pre-restart behavior.
External Checkpoint Storage
AgentVisor stores checkpoints and pending writes entirely inside Temporal workflow
history, which inherits Temporal's own per-payload ceiling. External Checkpoint
Storage lets a payload at or above threshold be stored in a pluggable backend
instead, raising that ceiling without giving up the zero-infrastructure,
workflow-native storage model that stays the default.
| Env var | Description |
|---|---|
AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_CALL_TIMEOUT | Timeout for each individual store/retrieve call to the checkpoint storage backend |
AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_ENABLED | Enable External Checkpoint Storage; workflow-native storage (plain Temporal history) stays the default |
AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_PROVIDER | Storage backend (e.g. memory, filesystem, postgresql, s3, ycql) — only registered backends are usable; required when enabled: true |
AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_THRESHOLD | Minimum serialized payload size in bytes that triggers storing a payload in the backend; smaller payloads stay inline in Temporal history |
AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_SWEEP_BATCH_SIZE | Number of keys a single safety-net sweep batch's scan and delete round trip handles |
AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_SWEEP_CALL_TIMEOUT | Timeout for each workflow-liveness check a safety-net sweep batch makes |
AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_SWEEP_CONCURRENCY | Maximum number of workflow-liveness checks a single safety-net sweep batch may have in flight at once |
AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_SWEEP_ENABLED | Enable the scheduled safety-net sweep that reclaims stored objects whose owning workflow execution has left Temporal retention — Temporal itself never garbage-collects checkpoint storage payloads |
AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_SWEEP_GRACE_PERIOD | Minimum age an object must reach before a sweep will consider reclaiming it, so an in-flight upload is never reclaimed out from under its own claim |
AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_SWEEP_INTERVAL | How often the scheduled safety-net sweep runs |
AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_SWEEP_LIVE_CACHE_SIZE | Maximum number of distinct workflow executions a single safety-net sweep batch tracks to dedupe repeated liveness checks, bounded via LRU eviction |
AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_SWEEP_RATE_LIMIT | Maximum aggregate rate, in workflow-liveness checks per second, a safety-net sweep issues across every batch it processes |
AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_CLEANUP_RETENTION_MARGIN | Safety buffer added to a namespace's own retention period before the per-thread cleanup mechanism re-checks whether an object's owning execution has left retention |
AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_CIRCUIT_BREAKER_FAILURE_THRESHOLD | Number of consecutive checkpoint storage call failures that trips the circuit breaker open |
AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_CIRCUIT_BREAKER_RESET_TIMEOUT | How long the checkpoint storage circuit breaker stays open before allowing a single probe call through |
temporal:
checkpoint_storage:
call_timeout: "10s"
circuit_breaker:
failure_threshold: 5
reset_timeout: "30s"
cleanup:
retention_margin: "1h"
enabled: false
provider: ""
sweep:
batch_size: 100
call_timeout: "10s"
concurrency: 10
enabled: true
grace_period: "24h"
interval: "24h"
live_cache_size: 4096
rate_limit: 20
threshold: 1048576
Disabling External Checkpoint Storage
Flipping checkpoint_storage.enabled from true back to false while
checkpoint_storage.provider is still set is rejected at startup by default.
Once a thread's history references an object stored in the backend (a
checkpoint, a Continue-As-New payload, or a pending-write batch), that
reference can only be resolved while the same storage backend stays
configured — if this host restarts without it, that thread can never be
replayed again. A non-empty provider left in place alongside
enabled: false is treated as a strong signal the operator likely flipped
the boolean without removing the rest of the config.
To disable the feature safely, remove temporal.checkpoint_storage.provider
entirely once you are certain no thread ever stored a payload there. To
override the check anyway (a break-glass escape hatch, following the same
convention as AGENTVISOR_TLS_ALLOW_INSECURE),
set:
AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_ALLOW_DISABLE=true
Enabling checkpoint_storage requires temporal.max_put_writes_per_execution (above) to
be set to a non-zero value — with payloads moved to the backend, workflow history shrinks
in bytes, so Temporal's own history-size-based Continue-As-New suggestion fires much
later, and a run could otherwise accumulate an unbounded number of put_writes Update
events. Startup validation rejects the combination of checkpoint_storage.enabled: true
with max_put_writes_per_execution: 0.
checkpoint_storage.enabled: true alone raises the automatic
temporal.max_checkpoint_bytes ceiling from 1 MiB to 8 MiB — the guest's own
write-time validation ceiling is max_checkpoint_bytes, so this is what actually
gives a checkpoint room to grow past threshold before the feature has anything to
do. Setting max_checkpoint_bytes explicitly always wins over the automatic value. See
Checkpoint Sizing and Limits: Raising the
Ceiling for the full picture of
what that knob governs and what derives from it.
Startup validation keeps the two fields consistent: threshold must stay below
max_checkpoint_bytes whenever checkpoint storage is enabled, and must never exceed
1.5 MiB regardless (a payload at or below threshold stays inline in Temporal
workflow history, where Temporal's raw per-payload ceiling still binds). With storage
disabled, max_checkpoint_bytes is capped at roughly 1.33 MiB — the largest value
whose derived Continue-As-New budget still lands on Temporal's raw ~2 MiB per-payload
ceiling — since nothing would move an oversized payload out of workflow history.
Provider-specific options use temporal.checkpoint_storage.<provider>.* in config files,
or AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_<PROVIDER>_<KEY> as environment variables — the
same shape as Store's provider options:
temporal:
checkpoint_storage:
enabled: true
provider: postgresql
postgresql:
connection_string: "postgres://user:pass@localhost:5432/agentvisor"
# Same tls_*/pool_* options as the postgresql store provider (see Store below).
# statement_timeout: "30s" # optional; server-enforced backstop, independent
# of the checkpoint storage driver's own context-based
# call deadline -- unset by default, like connect_timeout
Or via environment variables:
AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_POSTGRESQL_CONNECTION_STRING=postgres://user:pass@localhost:5432/agentvisor
The s3 provider talks to Amazon S3 or an S3-compatible service (e.g. MinIO):
temporal:
checkpoint_storage:
enabled: true
provider: s3
s3:
bucket: "agentvisor-blobstore" # required
region: "us-east-1" # optional; falls back to the AWS SDK's
# default resolution (env vars, shared config)
key_prefix: "agentvisor/blobstore" # optional; "" means the bucket root
# Static credentials (optional; falls back to the AWS SDK's default credential
# chain -- env vars, shared config, IAM role, etc.):
# access_key_id: "..."
# secret_access_key: "..."
# session_token: "..."
# Custom endpoint for S3-compatible backends. Must include a scheme
# (http:// or https://). use_path_style defaults to true whenever endpoint is
# set (most S3-compatible services require path-style addressing) and to
# false otherwise.
# endpoint: "http://localhost:9000"
# use_path_style: true
# Same tls_*/tls_trust_system_roots options as the postgresql provider above,
# applied only to a custom endpoint -- real AWS S3 relies on the SDK's own
# default HTTPS transport.
Or via environment variables:
AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_S3_BUCKET=agentvisor-blobstore
AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_S3_REGION=us-east-1
The ycql provider talks to a YugabyteDB cluster over its Cassandra-compatible YCQL
protocol:
temporal:
checkpoint_storage:
enabled: true
provider: ycql
ycql:
hosts: "10.0.0.1,10.0.0.2,10.0.0.3" # required; comma-separated contact points
# (or a YAML list in a config file)
keyspace: "agentvisor" # required; must already exist -- this
# provider never creates it, matching the
# postgresql provider's expectation that its
# database already exists
# table: "blobstore_objects" # optional; default shown
# port: 9042 # optional; gocql default
# username: "..." # optional; set together with password,
# password: "..." # or not at all
# consistency: "quorum" # optional; any gocql consistency level name
# timeout: "8s" # optional; per-query timeout. Default
# (shown) is below the checkpoint storage
# driver's 10s per-call deadline, not gocql's
# own native 11s -- otherwise the outer
# context, not gocql, is what actually
# cancels a wedged call
# connect_timeout: "8s" # optional; same default reasoning as
# timeout above
# num_conns: 2 # optional; connections per host
# page_size: 5000 # optional; rows fetched per page for a
# Scan query. Default (shown) is gocql's
# own library default
# retry_num_retries: 3 # optional; SimpleRetryPolicy's retry
# count. Default (shown) replaces
# gocql's own default of no retry at
# all; set to 0 to explicitly disable
# disable_initial_host_lookup: false # optional; set true behind a NAT, port-
# forward, or other address-translating
# indirection (e.g. a dynamically-mapped
# container port) -- otherwise gocql
# replaces the configured hosts with
# unreachable internal addresses
# discovered from system.peers. Costs
# token-aware/DC-aware routing.
# ttl: "720h" # optional row-expiry TTL -- an opt-in backstop
# alongside the cleanup mechanism, not a
# substitute for it (TTL alone can't express
# run-liveness-aware reclamation)
# buckets: 16 # optional; number of hash buckets the
# Scan-serving secondary index is
# partitioned over. Default (shown) turns
# what would otherwise be one partition
# for the whole deployment into 16. Must
# stay fixed for the lifetime of a
# deployment's data -- changing it strands
# previously-written objects from future
# Scan calls (Get/Delete by exact key are
# unaffected).
# Same tls_*/tls_trust_system_roots options as the postgresql provider above.
Or via environment variables:
AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_YCQL_HOSTS=10.0.0.1,10.0.0.2,10.0.0.3
AGENTVISOR_TEMPORAL_CHECKPOINT_STORAGE_YCQL_KEYSPACE=agentvisor
The filesystem provider accepts a single dir option (default: <cache_dir>/blobstore);
memory accepts no options and does not survive a process restart, so it is intended for
throwaway testing only.
get_checkpoint, list_checkpoints, and getState reads are covered the same way writes
are: a read result at or above threshold is served from the configured backend too, so a
checkpoint written past Temporal's raw ~2MiB per-payload ceiling reads back correctly, and
a thread whose head checkpoint has grown that large keeps running normally. See
Checkpoint Sizing and Limits for
how to size a threshold and pinned ceiling, and the External Checkpoint Storage
guide for the full operational picture.
Authorization
AgentVisor uses the Manetu PolicyEngine (MPE) for request authorization. The provider is pluggable.
| Env var | Description |
|---|---|
AGENTVISOR_AUTHZ_TYPE | Authorization provider: embedded (local MPE), http (remote PDP), or allowall (dev only) |
HTTP Provider
Delegates policy decisions to a remote Policy Decision Point (PDP) server.
| Env var | Description |
|---|---|
AGENTVISOR_AUTHZ_HTTP_TIMEOUT | HTTP request timeout for policy evaluation calls to the remote PDP |
AGENTVISOR_AUTHZ_HTTP_URL | URL of the remote HTTP Policy Decision Point (PDP) server |
AGENTVISOR_AUTHZ_HTTP_TLS_CA_DATA | Base64-encoded PEM CA certificate for verifying the PDP server (alternative to ca_file) |
AGENTVISOR_AUTHZ_HTTP_TLS_CA_FILE | Path to PEM CA certificate for verifying the PDP server |
AGENTVISOR_AUTHZ_HTTP_TLS_CERT_DATA | Base64-encoded PEM client certificate for mTLS to the PDP (alternative to cert_file) |
AGENTVISOR_AUTHZ_HTTP_TLS_CERT_FILE | Path to PEM client certificate for mTLS authentication to the PDP |
AGENTVISOR_AUTHZ_HTTP_TLS_KEY_DATA | Base64-encoded PEM client private key for mTLS to the PDP (alternative to key_file) |
AGENTVISOR_AUTHZ_HTTP_TLS_KEY_FILE | Path to PEM client private key for mTLS authentication to the PDP |
AGENTVISOR_AUTHZ_HTTP_TLS_MODE | TLS verification mode: verify-full (default), verify-ca, require, or disable |
AGENTVISOR_AUTHZ_HTTP_TLS_SERVER_NAME | TLS SNI server name override (useful when PDP is behind a proxy/load balancer) |
AGENTVISOR_AUTHZ_HTTP_TLS_TRUST_SYSTEM_ROOTS | Append the configured CA to the system root pool instead of replacing it (default: false) |
authz:
http:
timeout: ""
tls:
ca_data: ""
ca_file: ""
cert_data: ""
cert_file: ""
key_data: ""
key_file: ""
mode: ""
server_name: ""
trust_system_roots: false
url: ""
authz.http.headers (custom request headers to the PDP) can only be configured via YAML — not
via flat environment variables. Use value_env within a header entry to reference a secret at
startup.
Embedded Provider
The embedded provider runs the Manetu PolicyEngine locally using Rego evaluation. Configure via provider-specific env vars:
| Variable | Default | Description |
|---|---|---|
AGENTVISOR_AUTHZ_EMBEDDED_POLICY_DOMAIN_FILES | - | Comma-separated paths to MPE policy domain YAML files (required) |
AGENTVISOR_AUTHZ_EMBEDDED_ACCESS_LOG_OUTPUT | stdout | Access log destination: stdout, stderr, logger, discard, /path, rotate:/path. In exec mode defaults to logger. |
AGENTVISOR_AUTHZ_EMBEDDED_ACCESS_LOG_FORMAT | json | JSON formatting: json (compact) or pretty (indented). Ignored for logger/discard. |
AGENTVISOR_AUTHZ_EMBEDDED_ACCESS_LOG_LEVEL | info | Log level when ACCESS_LOG_OUTPUT=logger. |
AGENTVISOR_AUTHZ_EMBEDDED_ACCESS_LOG_PRETTY_PRINT | false | Deprecated — use ACCESS_LOG_FORMAT=pretty. |
# Embedded provider (recommended for most deployments)
authz:
type: embedded
embedded:
policy_domain_files: /etc/agentvisor/policies/domain.yml
# HTTP provider (remote PDP)
# authz:
# type: http
# http:
# url: https://pdp.example.com:9000
# timeout: 5s
# tls:
# mode: verify-full
# ca_file: /etc/agentvisor/pdp-ca.pem
# headers:
# - name: "X-Tenant-ID"
# value: "acme"
# - name: "Authorization"
# value_env: "PDP_TOKEN"
# AllowAll provider (development only — NEVER use in production!)
# authz:
# type: allowall
HTTP Proxy
The HTTP proxy provides TLS termination and credential substitution for outbound agent requests.
Agents route through the proxy transparently via the HTTPS_PROXY environment variable injected at
guest startup.
| Env var | Description |
|---|---|
AGENTVISOR_PROXY_ALLOWED_PATTERNS | No longer supported; rejected at config load. Restrict outbound destinations via MPE HTTP policy (mrn:agentvisor:http:<host>/<path>) instead |
AGENTVISOR_PROXY_INTERCEPT_CACHE_TTL | Max lifetime of a response_intercept resolver's cached symbolic-to-real credential mapping (e.g. intercepted OAuth tokens) |
AGENTVISOR_PROXY_MAX_BODY_SIZE | Maximum buffered response body size in bytes for unary proxy requests |
AGENTVISOR_PROXY_REQUEST_TIMEOUT | Timeout for HTTP proxy requests forwarded to upstream services |
AGENTVISOR_PROXY_SSRF_ALLOWED_CIDRS | Destinations (CIDR range, bare IP, or bare hostname) exempted from the SSRF guard's default-deny of loopback, unspecified, link-local (incl. cloud metadata), private, and carrier-grade-NAT destinations. A hostname entry is resolved at startup and every resolved address is allowed -- the recommended way to allowlist "localhost", since a CIDR-only entry for one address family (e.g. 127.0.0.1/32) does not also cover ::1 |
AGENTVISOR_PROXY_STREAM_MAX_BODY_SIZE | Maximum streaming response body size in bytes for streaming proxy requests |
AGENTVISOR_PROXY_UPSTREAM_TLS_CA_DATA | Base64-encoded PEM CA certificate to trust for upstream requests (alternative to ca_file) |
AGENTVISOR_PROXY_UPSTREAM_TLS_CA_FILE | Path to PEM CA certificate to trust for upstream requests (e.g. a private/internal CA) |
AGENTVISOR_PROXY_UPSTREAM_TLS_TRUST_SYSTEM_ROOTS | Append the configured CA to the system root pool instead of replacing it (default: true — unlike every other TLS site, the proxy must reach both private and public destinations) |
proxy:
intercept_cache_ttl: "15m"
max_body_size: 10485760
request_timeout: "5m"
ssrf_allowed_cidrs: []
stream_max_body_size: 209715200
upstream_tls:
ca_data: ""
ca_file: ""
trust_system_roots: true
Credential substitution (injecting real API keys while agents use placeholder tokens) is configured
under proxy.credentials. See Proxy Credentials for the full reference.
proxy.upstream_tls configures which CA(s) the proxy trusts when dialing agent-chosen upstream
destinations — narrower than other TLS sites (no mode, server_name, or client certs). See
TLS Trust Configuration for the full reference.
API Server
All API transports share a single HTTP server with common listen address, connection limits, timeouts, and body size settings.
| Env var | Description |
|---|---|
AGENTVISOR_API_IDLE_TIMEOUT | Maximum time an idle connection is kept open |
AGENTVISOR_API_LISTEN_ADDR | Listen address shared by all API transports (e.g. :8090) |
AGENTVISOR_API_MAX_BODY_SIZE | Maximum request body size in bytes; requests exceeding this receive 413 |
AGENTVISOR_API_MAX_CONNECTIONS | Maximum concurrent connections; requests over this limit receive 503 |
AGENTVISOR_API_MAX_CONNECTIONS_PER_IP | Maximum concurrent connections per client IP; excess receives 503 |
AGENTVISOR_API_MIN_BODY_RATE | Minimum upload rate in bytes/s; connections below this are terminated (slow-loris protection) |
AGENTVISOR_API_READ_BODY_TIMEOUT | Maximum duration for reading the complete request body |
AGENTVISOR_API_TRUSTED_PROXIES | CIDR ranges of reverse proxies trusted to set X-Forwarded-For/X-Real-IP (comma-separated); empty (default) ignores these headers and uses RemoteAddr |
AGENTVISOR_API_WRITE_TIMEOUT | Maximum duration for writing the response (disabled for SSE endpoints) |
api:
idle_timeout: "2m"
listen_addr: ":8090"
max_body_size: 10485760
max_connections: 10000
max_connections_per_ip: 100
min_body_rate: 1024
read_body_timeout: "1m"
trusted_proxies: []
write_timeout: "1m"
API Authentication
Authentication is shared across all API transports. When enabled, all requests must present a valid OIDC JWT.
| Env var | Description |
|---|---|
AGENTVISOR_API_AUTH_ENABLED | Require OIDC authentication for all API requests |
AGENTVISOR_API_AUTH_OIDC_ALLOW_INSECURE | Permit plaintext http:// OIDC endpoints — an on-path attacker can substitute signing keys; never enable in production (loopback hosts are always permitted) |
AGENTVISOR_API_AUTH_OIDC_AUDIENCE | Expected OIDC aud claim value |
AGENTVISOR_API_AUTH_OIDC_ISSUER | OIDC issuer URL for token validation |
AGENTVISOR_API_AUTH_OIDC_JWKS_URL | Override JWKS URL (must be https; use when discovered URL is not reachable, e.g. inside K8s) |
AGENTVISOR_API_AUTH_TEST_MODE | Allow principal injection via X-Test-Principal header — never enable in production |
AGENTVISOR_API_AUTH_TLS_CA_DATA | Base64-encoded PEM CA certificate for verifying the OIDC provider (alternative to ca_file) |
AGENTVISOR_API_AUTH_TLS_CA_FILE | Path to PEM CA certificate for verifying the OIDC provider |
AGENTVISOR_API_AUTH_TLS_CERT_DATA | Base64-encoded PEM client certificate for mTLS to the OIDC provider (alternative to cert_file) |
AGENTVISOR_API_AUTH_TLS_CERT_FILE | Path to PEM client certificate for mTLS authentication to the OIDC provider |
AGENTVISOR_API_AUTH_TLS_KEY_DATA | Base64-encoded PEM client private key for mTLS to the OIDC provider (alternative to key_file) |
AGENTVISOR_API_AUTH_TLS_KEY_FILE | Path to PEM client private key for mTLS authentication to the OIDC provider |
AGENTVISOR_API_AUTH_TLS_MODE | TLS verification mode: verify-full (default), verify-ca, require, or disable |
AGENTVISOR_API_AUTH_TLS_SERVER_NAME | TLS SNI server name override (useful when the OIDC provider is behind a proxy/load balancer) |
AGENTVISOR_API_AUTH_TLS_TRUST_SYSTEM_ROOTS | Append the configured CA to the system root pool instead of replacing it (default: false) |
api:
auth:
enabled: false
oidc_allow_insecure: false
oidc_audience: ""
oidc_issuer: ""
oidc_jwks_url: ""
test_mode: false
tls:
ca_data: ""
ca_file: ""
cert_data: ""
cert_file: ""
key_data: ""
key_file: ""
mode: ""
server_name: ""
trust_system_roots: false
api.auth.tls configures outbound trust for the discovery document fetch and
JWKS fetch made against oidc_issuer / oidc_jwks_url (e.g. tls.ca_file to
trust a private CA). See
TLS Trust Configuration for the
full field reference.
API Transports
API Transports control how external clients access AgentVisor agents. Each transport can be independently enabled or disabled.
Don't confuse API Transports (inbound — external clients → agents) with Service Gateways (outbound — agents → external services):
api.mcp.enabledenables the MCP Transport (external MCP clients → agents)mcp.servers[]configures the MCP Gateway (agents → external MCP servers)
See MCP Gateway and A2A Gateway below for gateway configuration.
| Env var | Description |
|---|---|
AGENTVISOR_API_OPENAPI_ENABLED | Enable OpenAPI/REST transport implementing LangGraph Agent Protocol v0.2.0 |
AGENTVISOR_API_MCP_ENABLED | Enable MCP transport at /mcp (exposes agents as MCP tools to external MCP clients) |
AGENTVISOR_API_MCP_TOOLS_AGENTS | Expose auto-generated per-agent invocation tools via MCP |
AGENTVISOR_API_MCP_TOOLS_RUNS | Expose run management tools via MCP (get_run, cancel_run, list_runs, wait_for_run) |
AGENTVISOR_API_MCP_TOOLS_STATE | Expose thread state tools via MCP (get_thread_state, update_thread_state) |
AGENTVISOR_API_MCP_TOOLS_STORE | Expose key-value store tools via MCP (store_put, store_get, store_delete, store_search) |
AGENTVISOR_API_MCP_TOOLS_SYSTEM | Expose system tools via MCP (health_check, list_agents) |
AGENTVISOR_API_MCP_TOOLS_THREADS | Expose thread management tools via MCP (create_thread, get_thread, delete_thread) |
AGENTVISOR_API_A2A_ENABLED | Enable A2A transport at /a2a (exposes agents via Google Agent-to-Agent Protocol) |
api:
openapi:
enabled: true
mcp:
enabled: false
tools:
agents: true
runs: true
state: true
store: true
system: true
threads: true
a2a:
enabled: false
Transport endpoints:
- OpenAPI/REST:
/*(root paths for threads, runs, agents, store, etc.) - MCP:
/mcp(Model Context Protocol, streamable HTTP) - A2A:
/a2aand/.well-known/agent-card.json(Google Agent-to-Agent Protocol)
API TLS
Enable HTTPS for the API server with optional mutual TLS (mTLS) for client authentication.
| Env var | Description |
|---|---|
AGENTVISOR_API_TLS_AUTO_CERT | Auto-generate a self-signed certificate on startup — development only |
AGENTVISOR_API_TLS_CERT_DATA | Base64-encoded server TLS certificate (alternative to cert_file) |
AGENTVISOR_API_TLS_CERT_FILE | Path to server TLS certificate file (PEM) |
AGENTVISOR_API_TLS_CLIENT_AUTH | Client certificate policy: none, request, require, verify, or require_and_verify |
AGENTVISOR_API_TLS_CLIENT_CA_FILE | Path to CA certificate for client certificate verification (mTLS) |
AGENTVISOR_API_TLS_ENABLED | Enable HTTPS for the API server |
AGENTVISOR_API_TLS_KEY_DATA | Base64-encoded server TLS private key (alternative to key_file) |
AGENTVISOR_API_TLS_KEY_FILE | Path to server TLS private key file (PEM) |
AGENTVISOR_API_TLS_MIN_VERSION | Minimum TLS version: 1.2 or 1.3 |
api:
tls:
auto_cert: false
cert_data: ""
cert_file: ""
client_auth: "none"
client_ca_file: ""
enabled: false
key_data: ""
key_file: ""
min_version: "1.2"
Client Authentication Modes
| Mode | Description |
|---|---|
none | No client certificate requested (default) |
request | Request client cert but don't require it |
require | Require any client cert (no verification) |
verify | Verify client cert if presented |
require_and_verify | Require and verify client cert (most secure for mTLS) |
Examples
Production TLS with mTLS:
api:
tls:
enabled: true
cert_file: /etc/agentvisor/tls/server.crt
key_file: /etc/agentvisor/tls/server.key
client_ca_file: /etc/agentvisor/tls/client-ca.crt
client_auth: require_and_verify
min_version: "1.3"
Development with auto-generated certificate:
api:
tls:
enabled: true
auto_cert: true # WARNING: Development only!
API Request Hardening
All hardening is enabled by default with sensible limits. Disabling any protection logs a WARNING at startup.
JSON Validation
| Env var | Description |
|---|---|
AGENTVISOR_API_VALIDATION_MAX_ARRAY_LENGTH | Maximum number of elements in any JSON array in a request body |
AGENTVISOR_API_VALIDATION_MAX_JSON_DEPTH | Maximum JSON nesting depth in request bodies |
AGENTVISOR_API_VALIDATION_MAX_JSON_KEYS | Maximum number of keys across an entire JSON request body |
AGENTVISOR_API_VALIDATION_MAX_METADATA_KEY_LENGTH | Maximum length of a metadata object key in characters |
AGENTVISOR_API_VALIDATION_MAX_METADATA_KEYS | Maximum number of keys in any metadata object |
AGENTVISOR_API_VALIDATION_MAX_METADATA_VALUE_LENGTH | Maximum length of a metadata object value in characters |
AGENTVISOR_API_VALIDATION_MAX_STRING_LENGTH | Maximum length of any single string value in a JSON request body |
AGENTVISOR_API_VALIDATION_STRICT_MODE | Reject JSON objects with duplicate keys |
api:
validation:
max_array_length: 10000
max_json_depth: 20
max_json_keys: 10000
max_metadata_key_length: 128
max_metadata_keys: 100
max_metadata_value_length: 4096
max_string_length: 1048576
strict_mode: true
Rate Limiting
Rate limiting uses the token bucket algorithm with per-client and global limits.
Per-client format: rate/period,burst, e.g. 100/min,20.
| Env var | Description |
|---|---|
AGENTVISOR_API_RATE_LIMIT_ENABLED | Enable HTTP API rate limiting |
AGENTVISOR_API_RATE_LIMIT_GLOBAL_BURST | Global burst capacity (maximum instantaneous requests across all clients) |
AGENTVISOR_API_RATE_LIMIT_GLOBAL_RPS | Global requests per second across all clients |
AGENTVISOR_API_RATE_LIMIT_MAX_CLIENTS | Maximum number of per-client rate limit tracking entries (LRU) |
AGENTVISOR_API_RATE_LIMIT_PER_CLIENT_AGENT_QUERIES | Per-client rate limit for agent list/query operations (format: rate/period,burst) |
AGENTVISOR_API_RATE_LIMIT_PER_CLIENT_RUN_CREATION | Per-client rate limit for run creation operations (format: rate/period,burst) |
AGENTVISOR_API_RATE_LIMIT_PER_CLIENT_RUN_POLLING | Per-client rate limit for run polling/wait operations (format: rate/period,burst) |
AGENTVISOR_API_RATE_LIMIT_PER_CLIENT_SSE_CONNECTIONS | Per-client rate limit for SSE stream connections (format: rate/period,burst) |
AGENTVISOR_API_RATE_LIMIT_PER_CLIENT_STORE_OPS | Per-client rate limit for key-value store operations (format: rate/period,burst) |
AGENTVISOR_API_RATE_LIMIT_PER_CLIENT_THREAD_CRUD | Per-client rate limit for thread create/read/update/delete (format: rate/period,burst) |
api:
rate_limit:
enabled: true
global_burst: 20000
global_rps: 10000
max_clients: 10000
per_client:
agent_queries: "100/min,30"
run_creation: "60/min,10"
run_polling: "300/min,50"
sse_connections: "10/min,5"
store_ops: "200/min,50"
thread_crud: "100/min,20"
Clients are identified by authenticated principal (sub claim) or client IP for anonymous
requests. Exceeded limits return 429 Too Many Requests with a Retry-After header.
CORS
CORS is restrictive by default (no cross-origin requests allowed).
| Env var | Description |
|---|---|
AGENTVISOR_API_CORS_ALLOW_ALL | Allow all CORS origins (Access-Control-Allow-Origin: *) — insecure, development only |
AGENTVISOR_API_CORS_ALLOW_CREDENTIALS | Allow cookies and authorization headers in cross-origin requests |
AGENTVISOR_API_CORS_ALLOWED_ORIGINS | Allowed CORS origins (comma-separated); supports exact match and *.example.com wildcards |
AGENTVISOR_API_CORS_MAX_AGE | Preflight cache duration in seconds |
api:
cors:
allow_all: false
allow_credentials: false
allowed_origins: []
max_age: 86400
*.example.com matches all subdomain depths. *.example.com allows both
https://app.example.com and https://deep.sub.example.com. For single-level semantics,
enumerate allowed origins explicitly.
Guest Sandbox
Configuration for the guest sandbox container that runs agent code in isolation.
| Env var | Description |
|---|---|
AGENTVISOR_GUEST_AGENT_LOG_CAPTURE_ROOT | Whether the Python SDK transparently captures idiomatic/third-party root-logger output via gRPC; forwarded to the guest/agent as AGENTVISOR_LOG_CAPTURE_ROOT |
AGENTVISOR_GUEST_BINARY_PATH | Path to the agentvisor-guest-runtime binary inside the guest container image (gVisor sandbox only; Docker uses the image ENTRYPOINT instead) |
AGENTVISOR_GUEST_BUNDLE_DIR | Directory for OCI bundle state (gVisor/Docker sandboxes) |
AGENTVISOR_GUEST_CPU_LIMIT | CPU limit as a fraction of one core (e.g. 1.0 = 1 CPU, 0 = unlimited) |
AGENTVISOR_GUEST_DOCKER_IMAGE | Docker image containing agent code (used by unified packaging mode) |
AGENTVISOR_GUEST_ENTRYPOINT | Agent entry-point file for sandbox: none mode |
AGENTVISOR_GUEST_ENVIRONMENT_FILES | Comma-separated paths to .env files whose variables are passed to the guest |
AGENTVISOR_GUEST_ENVIRONMENT_PASSTHROUGH | Host environment variable names to forward into the guest sandbox (comma-separated; use HOST=GUEST to rename) |
AGENTVISOR_GUEST_FSIZE_HARD_LIMIT | Hard RLIMIT_FSIZE (maximum file size, bytes) for the guest |
AGENTVISOR_GUEST_FSIZE_SOFT_LIMIT | Soft RLIMIT_FSIZE (maximum file size, bytes) for the guest |
AGENTVISOR_GUEST_GVISOR_DEBUG | Enable gVisor debug logging (runsc --debug); output is captured through the host logger |
AGENTVISOR_GUEST_GVISOR_PLATFORM | gVisor platform: `` (auto), systrap, ptrace, or kvm |
AGENTVISOR_GUEST_GVISOR_SECCOMP | Apply OCI seccomp profile to gVisor sandbox (--oci-seccomp); disable only to debug startup failures |
AGENTVISOR_GUEST_IMAGE | Pre-built guest OCI image reference; pulled and extracted at runtime instead of using a local rootfs |
AGENTVISOR_GUEST_INTERPRETER | Language interpreter for agent code (e.g. python3) |
AGENTVISOR_GUEST_MEMORY_LIMIT | Memory limit for the guest sandbox in bytes |
AGENTVISOR_GUEST_NPROC_HARD_LIMIT | Hard RLIMIT_NPROC (maximum processes) for the guest |
AGENTVISOR_GUEST_NPROC_SOFT_LIMIT | Soft RLIMIT_NPROC (maximum processes) for the guest |
AGENTVISOR_GUEST_PIDS_LIMIT | Maximum number of processes (PIDs) inside the guest |
AGENTVISOR_GUEST_PRINCIPAL | Guest identity principal for sandbox: none mode |
AGENTVISOR_GUEST_ROOTFS_PATH | Path to the guest root filesystem (OCI rootfs or pre-extracted image) |
AGENTVISOR_GUEST_ROOTLESS | Run gVisor in rootless mode using user namespaces (no --privileged required) |
AGENTVISOR_GUEST_RUNSC_PATH | Path to the runsc binary (gVisor runtime) |
AGENTVISOR_GUEST_RUNTIME_ROOT | Root directory for gVisor/container runtime state |
AGENTVISOR_GUEST_SANDBOX | Sandbox mode: gvisor (production), docker (development), or none (local debug) |
AGENTVISOR_GUEST_SHUTDOWN_TIMEOUT | Maximum time to wait for the guest sandbox to shut down gracefully |
AGENTVISOR_GUEST_SOURCE_DIR | Path to agent source code on the host (used with sandbox: none) |
AGENTVISOR_GUEST_STARTUP_TIMEOUT | Maximum time to wait for the guest sandbox to become ready |
AGENTVISOR_GUEST_VENV_PATH | Path to Python virtual environment (used by unified packaging with sandbox: none) |
AGENTVISOR_GUEST_WORK_DIR | Working directory inside the guest sandbox |
guest:
agent_log_capture_root: true
binary_path: "/usr/local/bin/agentvisor-guest-runtime"
bundle_dir: "/var/run/agentvisor/bundles"
cpu_limit: 0
docker_image: ""
entrypoint: "main.py"
environment_files: ""
environment_passthrough: []
fsize_hard_limit: 209715200
fsize_soft_limit: 104857600
gvisor_debug: false
gvisor_platform: ""
gvisor_seccomp: true
image: ""
interpreter: "python3"
memory_limit: 536870912
nproc_hard_limit: 512
nproc_soft_limit: 256
pids_limit: 1024
principal: ""
rootfs_path: "/opt/guest-rootfs"
rootless: true
runsc_path: "runsc"
runtime_root: "/var/run/agentvisor/runtime"
sandbox: "gvisor"
shutdown_timeout: "10s"
source_dir: ""
startup_timeout: "30s"
venv_path: ""
work_dir: ""
Fields specific to sandbox: none (local debugging without isolation): source_dir, entrypoint,
interpreter, principal, venv_path.
Registry Authentication
For pulling pre-built guest OCI images (guest.image):
| Env var | Description |
|---|---|
AGENTVISOR_GUEST_REGISTRY_AUTH_DOCKER_CONFIG | Path to Docker config.json for registry credential helpers (alternative to username/password env) |
AGENTVISOR_GUEST_REGISTRY_AUTH_PASSWORD_ENV | Environment variable name containing the registry password/token |
AGENTVISOR_GUEST_REGISTRY_AUTH_USERNAME_ENV | Environment variable name containing the registry username |
guest:
registry_auth:
docker_config: ""
password_env: ""
username_env: ""
Registry TLS
Outbound TLS trust for registry pull/push operations (guest image, mcp-tools image, and the
agentvisor build/build guest CLI commands). Like the egress proxy's proxy.upstream_tls,
this exposes a narrower ca_file/ca_data/trust_system_roots-only shape rather than the full
tlsutil.TrustConfig, since a registry client commonly reaches both private and arbitrary public
registries through the same client. See TLS Configuration for the
full outbound-TLS reference.
| Env var | Description |
|---|---|
AGENTVISOR_GUEST_REGISTRY_TLS_CA_DATA | Base64-encoded PEM CA certificate to trust for registry pull/push (alternative to ca_file) |
AGENTVISOR_GUEST_REGISTRY_TLS_CA_FILE | Path to a PEM CA certificate to trust when pulling/pushing images from a private-CA registry |
AGENTVISOR_GUEST_REGISTRY_TLS_INSECURE | Skip TLS certificate verification for registry operations; requires AGENTVISOR_TLS_ALLOW_INSECURE=true |
AGENTVISOR_GUEST_REGISTRY_TLS_TRUST_SYSTEM_ROOTS | Append the configured CA to the system root pool instead of replacing it (default true) |
guest:
registry_tls:
ca_data: ""
ca_file: ""
insecure: false
trust_system_roots: true
Equivalent CLI flags on build, build guest, run, serve, and exec: --registry-ca-file,
--registry-ca-data, --registry-insecure.
Sandbox Modes
| Mode | Platform | Hardening | Use Case |
|---|---|---|---|
none | Any | None | Local debugging (no isolation) |
docker | Linux | Full | Development with security |
docker | macOS/Windows | Full† | Development (CLI default) |
gvisor | Linux | Full | Production (host runtime default) |
†Docker on macOS/Windows uses nftables-based network isolation instead of --network=none.
Guest Hardening
Granular security hardening for the guest sandbox. Each feature defaults to auto, which enables
it when the sandbox supports it.
| Env var | Description |
|---|---|
AGENTVISOR_GUEST_HARDENING_ENV_CURATION | Environment curation: allowlist system env vars and set umask 0077 (auto, enabled, disabled) |
AGENTVISOR_GUEST_HARDENING_FILESYSTEM_HARDENING | Filesystem hardening: read-only rootfs, seccomp profiles, tmpfs mounts, masked paths (auto, enabled, disabled) |
AGENTVISOR_GUEST_HARDENING_KERNEL_HARDENING | Kernel hardening: capability bounding set, NoNewPrivileges, user-namespace blocking (auto, enabled, disabled) |
AGENTVISOR_GUEST_HARDENING_NETWORK_FILTERING | nftables outbound traffic filtering for TCP transport mode (Docker macOS/Windows) (auto, enabled, disabled) |
AGENTVISOR_GUEST_HARDENING_NETWORK_ISOLATION | Loopback-only networking (--network=none) (auto, enabled, disabled) |
AGENTVISOR_GUEST_HARDENING_PROCESS_ISOLATION | Privilege separation, UID isolation, and capability dropping (auto, enabled, disabled) |
guest:
hardening:
env_curation: "auto"
filesystem_hardening: "auto"
kernel_hardening: "auto"
network_filtering: "auto"
network_isolation: "auto"
process_isolation: "auto"
Hardening Values
| Value | Behavior |
|---|---|
auto | Enable if supported by sandbox type (default) |
enabled | Force enable — fails startup if not supported |
disabled | Force disable — WARNING logged |
Auto-Detection Matrix
| Feature | gvisor | docker (Linux) | docker (macOS/Win) | none |
|---|---|---|---|---|
process_isolation | ✓ | ✓ | ✓ | |
env_curation | ✓ | ✓ | ✓ | |
network_isolation | ✓ | ✓ | ||
network_filtering | ✓† | |||
filesystem_hardening | ✓ | ✓ | ✓ | |
kernel_hardening | ✓ | ✓ | ✓ |
†network_isolation and network_filtering are mutually exclusive. Docker on macOS/Windows uses
nftables-based outbound restriction (network_filtering) instead of --network=none.
See Sandbox Modes for detailed feature descriptions.
Guest Proxy Hardening
These settings configure connection limits and TLS parameters for the guest HTTP proxy. They are read by the guest-runtime (not the host-runtime config system) and can only be set via environment variables.
| Variable | Default | Description |
|---|---|---|
AGENTVISOR_GUEST_PROXY_LOG_LEVEL | none | Proxy request audit logging: none, summary, full |
AGENTVISOR_GUEST_PROXY_MAX_CONNECTIONS | 500 | Maximum total concurrent connections across all agents |
AGENTVISOR_GUEST_PROXY_MAX_CONNECTIONS_PER_AGENT | 50 | Maximum concurrent connections per agent |
AGENTVISOR_GUEST_PROXY_MAX_INFLIGHT_PER_AGENT | 20 | Maximum concurrent in-flight requests per agent |
AGENTVISOR_GUEST_PROXY_RATE_LIMIT_RPS | 100.0 | Per-agent request rate limit (requests per second) |
AGENTVISOR_GUEST_PROXY_RATE_LIMIT_BURST | 200 | Per-agent rate limit burst capacity |
AGENTVISOR_GUEST_PROXY_TLS_HANDSHAKE_TIMEOUT | 10s | Maximum time for TLS handshake |
AGENTVISOR_GUEST_PROXY_CONN_MAX_DURATION | 30m | Maximum connection duration before forced close |
Per-host TLS certificate settings (guest ephemeral CA):
| Variable | Default | Description |
|---|---|---|
AGENTVISOR_GUEST_CA_VALIDITY | 720h | Validity period for the ephemeral CA certificate |
AGENTVISOR_GUEST_CERT_VALIDITY | 1h | Validity period for per-host TLS certificates |
AGENTVISOR_GUEST_CERT_EVICTION_INTERVAL | 5m | Interval for evicting expired certificates from cache |
Guest Runtime Size & Rate Limits
These settings configure size limits for the guest-runtime's per-agent control surface. They are read by the guest-runtime and can only be set via environment variables.
| Variable | Default | Description |
|---|---|---|
AGENTVISOR_GUEST_CHECKPOINT_MAX_SIZE | 50MB | Sizes the guest↔host gRPC transport envelope for SaveCheckpoint/LoadCheckpoint calls — not itself a checkpoint-size ceiling. The real per-checkpoint ceiling is temporal.max_checkpoint_bytes (see Checkpoint Sizing and Limits); startup validation rejects this setting if lowered below the resolved max_checkpoint_bytes value |
AGENTVISOR_GUEST_STORE_VALUE_MAX_SIZE | 10MB | Maximum store value size |
AGENTVISOR_GUEST_STREAM_CHUNK_MAX_SIZE | 1MB | Maximum stream chunk data size |
AGENTVISOR_GUEST_LOG_MESSAGE_MAX_SIZE | 64KB | Maximum log message size |
Each AGENTVISOR_GUEST_RATELIMIT_* variable below caps one AgentService RPC category with a
per-agent token bucket, format "<rate>/s,<burst>" (e.g. "10/s,20" = 10 requests/second,
burst capacity 20). They are read by the guest-runtime and can only be set via environment
variables.
| Variable | Default | Description |
|---|---|---|
AGENTVISOR_GUEST_RATELIMIT_HEARTBEAT | 10/s,20 | Heartbeat operations |
AGENTVISOR_GUEST_RATELIMIT_CHECKPOINT | 5/s,10 | SaveCheckpoint, LoadCheckpoint, DeleteCheckpoints, and ListCheckpoints operations share this bucket |
AGENTVISOR_GUEST_RATELIMIT_PUTWRITES | 50/s,100 | Pending-write operations; kept separate from RATELIMIT_CHECKPOINT because it fires once per task per LangGraph superstep — a meaningfully higher frequency than SaveCheckpoint's once-per-superstep |
AGENTVISOR_GUEST_RATELIMIT_STORE | 50/s,100 | Key-value store operations |
AGENTVISOR_GUEST_RATELIMIT_MCP | 20/s,50 | MCP gateway operations |
AGENTVISOR_GUEST_RATELIMIT_STREAM | 100/s,200 | Stream chunk operations |
AGENTVISOR_GUEST_RATELIMIT_LOG | 100/s,500 | Log forwarding operations |
AGENTVISOR_GUEST_RATELIMIT_INVALIDCALL | 10/s,20 | Validation-rejected calls; a separate sub-bucket so adversarial invalid requests can't starve legitimate operations in the per-category buckets above |
AGENTVISOR_GUEST_RATELIMIT_TRACING | 20/s,50 | ForwardSpans (OpenTelemetry trace export) operations |
AGENTVISOR_GUEST_RATELIMIT_STATE | 50/s,100 | Thread state operations (StateGet, StatePut, StateDelete, StateList) |
AGENTVISOR_GUEST_RATELIMIT_A2A | 20/s,50 | A2A gateway operations |
Guest Python Debugging
AgentVisor supports interactive debugging with VS Code and PyCharm via debugpy and pydevd.
Only available with sandbox: none.
| Env var | Description |
|---|---|
AGENTVISOR_GUEST_DEBUG_ENABLED | Enable Python remote debugging (supported only with sandbox: none) |
AGENTVISOR_GUEST_DEBUG_HOST | Debugger listen host/IP |
AGENTVISOR_GUEST_DEBUG_PORT | Debugger listen port |
AGENTVISOR_GUEST_DEBUG_PROVIDER | Debug provider: debugpy (VS Code) or pydevd (PyCharm) |
AGENTVISOR_GUEST_DEBUG_WAIT_FOR_CLIENT | Block agent startup until the debugger attaches |
guest:
debug:
enabled: false
host: "0.0.0.0"
port: 5678
provider: "debugpy"
wait_for_client: true
Debug Providers
| Provider | Protocol | Best For | Install |
|---|---|---|---|
debugpy | DAP | VS Code, any DAP client | pip install debugpy |
pydevd | pydevd | PyCharm native features | pip install pydevd-pycharm |
agentvisor serve ./my-agent --sandbox=none --debug
agentvisor serve ./my-agent --sandbox=none --debug --debug-provider=pydevd
Guest SDK Retry
The Python SDK automatically retries transient gRPC errors (UNAVAILABLE,
DEADLINE_EXCEEDED, RESOURCE_EXHAUSTED) with exponential backoff.
Global Settings
| Env var | Description |
|---|---|
AGENTVISOR_GUEST_SDK_RETRY_BASE_DELAY_MS | Initial delay between SDK retries in milliseconds |
AGENTVISOR_GUEST_SDK_RETRY_ENABLED | Enable automatic retry for transient gRPC failures in the Python SDK |
AGENTVISOR_GUEST_SDK_RETRY_EXPONENTIAL_BASE | Exponential backoff multiplier for SDK retries |
AGENTVISOR_GUEST_SDK_RETRY_JITTER | Add randomized delay (jitter) to SDK retries to prevent thundering herd |
AGENTVISOR_GUEST_SDK_RETRY_MAX_ATTEMPTS | Maximum retry attempts including the initial attempt |
AGENTVISOR_GUEST_SDK_RETRY_MAX_DELAY_MS | Maximum delay between SDK retries in milliseconds |
guest:
sdk:
retry:
base_delay_ms: 100
enabled: true
exponential_base: 2
jitter: true
max_attempts: 3
max_delay_ms: 5000
Per-Operation Overrides
Each operation type can override the global settings. Available operations: checkpoint, store,
mcp, a2a, stream. Each supports: max_attempts, base_delay_ms, max_delay_ms,
exponential_base, jitter.
guest:
sdk:
retry:
# Global defaults shown above; per-operation overrides:
checkpoint:
max_attempts: 5
mcp:
max_attempts: 2
base_delay_ms: 500
See SDK Retry Reference for per-operation defaults and programmatic API.
Store
The Store API provides persistent key-value storage for agents. Disabled by default.
| Env var | Description |
|---|---|
AGENTVISOR_STORE_PROVIDER | Store backend: empty (disabled), sqlite (single-instance), or postgresql |
store:
provider: ""
Provider-specific options use store.<provider>.* in YAML or AGENTVISOR_STORE_<PROVIDER>_<KEY>
as env vars:
# SQLite (single-instance / development):
store:
provider: sqlite
sqlite:
db_path: /var/lib/agentvisor/store.db # default: <cache_dir>/store.db
# PostgreSQL (multi-instance deployments):
store:
provider: postgresql
postgresql:
connection_string: "postgres://user:pass@localhost:5432/agentvisor"
tls_mode: verify-full
tls_ca_file: /path/ca.crt
tls_cert_file: /path/client.crt
tls_key_file: /path/client.key
pool_max_conns: 10
connect_timeout: 10s
PostgreSQL env vars:
| Variable | Description |
|---|---|
AGENTVISOR_STORE_POSTGRESQL_CONNECTION_STRING | PostgreSQL connection URI |
AGENTVISOR_STORE_POSTGRESQL_TLS_MODE | SSL mode: disable, require, verify-ca, verify-full |
AGENTVISOR_STORE_POSTGRESQL_TLS_CA_FILE | CA certificate path |
AGENTVISOR_STORE_POSTGRESQL_TLS_CERT_FILE | Client certificate path |
AGENTVISOR_STORE_POSTGRESQL_TLS_KEY_FILE | Client private key path |
AGENTVISOR_STORE_POSTGRESQL_POOL_MAX_CONNS | Maximum pool connections (default: 4) |
AGENTVISOR_STORE_POSTGRESQL_CONNECT_TIMEOUT | Connection timeout (default: 2m) |
MCP Gateway
The MCP Gateway allows agents to access external MCP servers (GitHub, Slack, filesystem tools, etc.). AgentVisor manages connections and credentials on behalf of agents.
This section documents the MCP Gateway (agents → external MCP servers). To expose agents as
MCP tools to external clients (Claude Desktop, Cursor), see API Transports and
enable api.mcp.enabled.
Stdio Sandbox Image
When mcp.servers[] includes stdio entries and guest.sandbox is not none, AgentVisor runs each stdio MCP server inside a dedicated mcp-tools sandbox (providing node/npx and python/uvx). The rootfs for that sandbox is resolved using the following priority order (first match wins):
mcp.tools_rootfs_path— explicit pre-extracted directory on disk/opt/agentvisor/mcp-tools-rootfs— baked into images built withagentvisor build --bundle-mcp-tools- On-demand pull of
mcp.tools_image— pulled and cached on first use; defaults to the version-matchedghcr.io/manetu/agentvisor/agentvisor-mcp-tools:<version>
| Env var | Config key | Description |
|---|---|---|
AGENTVISOR_MCP_TOOLS_IMAGE | mcp.tools_image | OCI image reference for the mcp-tools sandbox. Defaults to the version-matched image from buildinfo. Consulted only when tools_rootfs_path is unset and the baked rootfs is absent. |
AGENTVISOR_MCP_TOOLS_ROOTFS_PATH | mcp.tools_rootfs_path | Path to a pre-extracted mcp-tools rootfs directory. Takes precedence over the baked rootfs and any image pull. |
mcp:
# tools_rootfs_path: "/path/to/pre-extracted/mcp-tools-rootfs" # AGENTVISOR_MCP_TOOLS_ROOTFS_PATH
# tools_image: "ghcr.io/manetu/agentvisor/agentvisor-mcp-tools:latest" # AGENTVISOR_MCP_TOOLS_IMAGE
See MCP Gateway: The mcp-tools Sandbox Image for the full explanation.
To pre-install npm or PyPI packages into the sandbox before startup, use mcp.prepull in mav-agent-config.yaml (not agentvisor.yaml). See MCP Gateway: Pre-installing Packages for the schema and usage.
Connection Pool
| Env var | Description |
|---|---|
AGENTVISOR_MCP_POOL_IDLE_TIMEOUT | Close idle principal-bound MCP connections after this duration |
AGENTVISOR_MCP_POOL_MAX_SIZE | Maximum connections in the principal-bound MCP LRU pool |
mcp:
pool:
idle_timeout: "5m"
max_size: 100
Startup Failure Posture
| Env var | Config key | Default | Description |
|---|---|---|---|
AGENTVISOR_MCP_ON_CONNECT_FAILURE | mcp.on_connect_failure | fail | Behavior when a static (non-principal-bound) MCP server fails to connect at startup. fail aborts startup; warn logs a warning and continues in a degraded state — the degraded status and failure counts are always visible via GET /ready regardless of this setting, while failed server names and failure classes are only disclosed to an authorized principal. |
mcp:
on_connect_failure: fail # fail | warn
Audit Logging
| Env var | Config key | Default | Description |
|---|---|---|---|
AGENTVISOR_MCP_LOG_LEVEL | mcp.log_level | summary | Verbosity of MCP gateway call audit logging: none, summary, full. Independent of both AGENTVISOR_LOG_LEVEL and a2a_gateway.log_level — mirrors the guest.proxy.log_level split between severity and audit detail. |
mcp:
log_level: summary # none | summary | full
Server Configuration
MCP servers are configured in the YAML file only (mcp.servers[] — not expressible as flat env
vars):
| Field | Required | Description |
|---|---|---|
name | Yes | Unique identifier for the server |
transport | Yes | Transport type: stdio, sse, or streamable_http |
command | stdio only | Command and arguments to launch the server |
url | HTTP only | Server URL |
env | No | Environment variables for stdio servers. Values support $VAR / ${VAR} expansion against host env vars (use $$ for a literal $). Unset variables log a warning and expand to "". |
credentials | No | Authentication configuration |
enrichment | No | Authz enrichment (rego or http provider) |
tls | HTTP only | Outbound TLS trust configuration for url. Rejected as a config error on stdio servers. |
Transport Types
| Transport | Description | When to Use |
|---|---|---|
stdio | Spawns a local process, communicates via stdin/stdout | Local tools (filesystem, git, shell) |
sse | Server-Sent Events over HTTP | Legacy remote MCP servers |
streamable_http | Bidirectional HTTP streaming | Modern remote MCP servers (recommended) |
Examples
mcp:
servers:
- name: filesystem
transport: stdio
command: ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/data"]
- name: github
transport: streamable_http
url: "https://api.githubcopilot.com/mcp/"
credentials:
type: bearer_token
source: env
env_var: GITHUB_TOKEN
- name: internal-service
transport: streamable_http
url: "https://internal.example.com/mcp"
credentials:
type: principal_passthrough
# tls: # Optional: trust a private CA for url
# mode: verify-ca
# ca_file: /etc/ssl/internal-service-ca.pem
- name: scoped-service
transport: streamable_http
url: "https://service.example.com/mcp"
credentials:
type: token_exchange
exchange_url: "https://auth.example.com/oauth/token"
audience: "service.example.com"
client_id: "agentvisor-client"
client_secret_env_var: "SERVICE_CLIENT_SECRET"
# tls: # Optional: trust a private CA for exchange_url
# mode: verify-ca
# ca_file: /etc/ssl/internal-idp-ca.pem
pool:
max_size: 100
idle_timeout: 5m
mcp.servers[].tls configures outbound trust for the connection to that
server's url (e.g. tls.ca_file to trust a private CA). Only valid for
sse/streamable_http transports — see
TLS Trust Configuration for the
full field reference.
Credential Types Reference
| Type | Fields | Description |
|---|---|---|
bearer_token | source, env_var | Static bearer token from env var |
api_key | header, source, env_var | Custom header with API key |
principal_passthrough | (none) | Forward caller's JWT |
token_exchange | exchange_url, audience, scope, subject_token_type, client_id, client_secret, client_secret_env_var, tls | RFC 8693 token exchange; supports confidential clients |
subject_token_type defaults to access_token, compatible with Keycloak and most OAuth 2.0
servers. Override with jwt, id_token, saml1, saml2, or a full URN if needed.
exchange_urltls configures outbound trust for the token_exchange resolver's call to
exchange_url (e.g. tls.ca_file to trust a private CA). See
TLS Trust Configuration
for the full field reference.
Connection Pool Behavior
- Static servers (no credentials,
bearer_token,api_key,stdio): Shared connections created at startup - Principal-bound servers (
principal_passthrough,token_exchange): Per-(server, principal) connections in LRU cache
Enrichment Definitions
The top-level enrichment.definitions section (a peer of mcp:/a2a_gateway:, not nested under either) lets you define a reusable enrichment provider configuration once and reference it by name from any mcp.servers[].enrichment or a2a_gateway.agents[].enrichment block via ref:, instead of repeating the same provider/options/rego fields at every site.
enrichment:
definitions:
- name: corp-http-enricher
provider: http
options:
url: https://enrich.example.com/enrich
timeout: 5s
tls:
mode: verify-full
ca_file: /etc/ssl/enrich-ca.pem
headers:
- { name: Authorization, value_env: ENRICH_TOKEN }
- name: repo-rego
provider: rego
rego_policy: /etc/agentvisor/policies/enrich.rego
| Field | Required | Description |
|---|---|---|
enrichment.definitions[].name | Yes | Unique identifier referenced by a site's ref: field. A duplicate name is a config validation error at startup. |
enrichment.definitions[].provider | Yes | Provider type: rego or http. |
enrichment.definitions[].options | Conditional | Provider-specific options (required for http; see http Provider Options below). |
enrichment.definitions[].rego_policy | Conditional | Path to a Rego policy file (rego provider). |
enrichment.definitions[].rego_policy_inline | Conditional | Inline Rego policy string (rego provider). |
Definitions must be fully inline — a definition cannot itself set ref, context, or headers (those are site-level overrides; see below).
This section is YAML-only; there is no flat AGENTVISOR_ENRICHMENT_DEFINITIONS_* environment variable form, consistent with other list-of-struct sections like mcp.servers[] and proxy.credentials[].
Authorization Enrichment
Enrichment is configured per MCP server (mcp.servers[].enrichment) or per A2A agent (a2a_gateway.agents[].enrichment) — the fields below are identical for both. A site can configure a provider fully inline, or reference a shared enrichment definition via ref:.
Fully inline:
mcp:
servers:
- name: github
transport: streamable_http
url: "https://api.githubcopilot.com/mcp/"
credentials:
type: bearer_token
source: env
env_var: GITHUB_TOKEN
enrichment:
provider: rego
rego_policy_inline: |
package agentvisor.authz.enrichment
result := {"operation": op, "resource": res} if {
input.tool_name == "list_commits"
repo := input.arguments.repo
op := sprintf("mcp:tool:github:repo:%v:commits:list", [repo])
res := sprintf("mrn:agentvisor:github:repo:%v", [repo])
}
Referencing a central definition, with per-site overrides:
mcp:
servers:
- name: github
enrichment:
ref: corp-http-enricher # see Enrichment Definitions above
context: # merged into the provider's site_context
site: github-mcp
environment: prod
headers: # http provider only; merged by header name
- { name: X-Enrichment-Site, value: github-mcp }
| Field | Required | Description |
|---|---|---|
provider | Conditional | Provider type: rego or http. Required unless ref is set; mutually exclusive with ref. |
options | Conditional | Provider-specific options. Required for http inline configs; mutually exclusive with ref. |
rego_policy | Conditional | Path to a Rego policy file (rego provider). Mutually exclusive with rego_policy_inline and ref. |
rego_policy_inline | Conditional | Inline Rego policy string (rego provider). Mutually exclusive with rego_policy and ref. |
ref | No | Name of an enrichment.definitions[] entry to use as the base configuration. Mutually exclusive with provider/options/rego_policy/rego_policy_inline. An unknown name fails startup. |
context | No | Arbitrary key/value map layered onto the resolved options as site_context — passed to rego as input.site_context and to http as the request body's site_context field. Works with or without ref. |
headers | No | []{name, value, value_env} list merged into the resolved http provider's headers, by header name (new names appended, matching names overridden). Ignored with a startup warning if the resolved provider is not http. |
rego_policy and rego_policy_inline are mutually exclusive — set exactly one when using the rego provider inline.
http Provider Options
The http enrichment provider's TLS/mTLS/header/timeout options follow the same shape and semantics as the authz HTTP Provider used for MPE/PDP authorization — see that section for TLS mode trade-offs.
enrichment:
definitions:
- name: corp-http-enricher
provider: http
options:
url: https://enrich.example.com/enrich # required
timeout: 5s # default: 5s
tls:
mode: verify-full # disable | require | verify-ca | verify-full (default: verify-full for https://)
ca_file: /etc/ssl/enrich-ca.pem
ca_data: ""
cert_file: /etc/ssl/client.pem # optional, for mTLS
cert_data: ""
key_file: /etc/ssl/client-key.pem
key_data: ""
server_name: enrich.internal # optional TLS SNI override
headers:
- name: Authorization
value_env: ENRICH_TOKEN # preferred: read from host env at startup
# value: "literal-value" # supported, but logs a startup warning
retry: # optional; shown values are the defaults
enabled: true # set false to disable retry entirely
max_attempts: 3 # total tries, including the first
initial_interval: 100ms
max_interval: 1s
max_elapsed_time: 1.5s # hard cap on total time spent retrying
| Field | Required | Description |
|---|---|---|
options.url | Yes | Enrichment endpoint. POSTed to verbatim — no path is appended (unlike the PDP provider, which appends /decision). |
options.timeout | No | Request timeout (default 5s). |
options.tls.mode | No | disable, require, verify-ca, or verify-full (default verify-full for https:// URLs). |
options.tls.ca_file / options.tls.ca_data | No | CA certificate for verifying the enrichment server (file path or base64-encoded PEM). |
options.tls.cert_file / options.tls.cert_data, options.tls.key_file / options.tls.key_data | No | Client certificate/key for mTLS. |
options.tls.server_name | No | TLS SNI override. |
options.headers[] | No | Static request headers ({name, value, value_env}); value_env is preferred over value to avoid committing secrets to version control. |
options.retry.enabled | No | Enables bounded retry for transient failures (default true). Set false to disable. |
options.retry.max_attempts | No | Total tries, including the first (default 3). |
options.retry.initial_interval | No | Initial exponential-backoff interval (default 100ms). |
options.retry.max_interval | No | Backoff interval cap (default 1s). |
options.retry.max_elapsed_time | No | Hard cap on total time spent retrying, across all attempts (default 1.5s). Bounds tail latency on this synchronous, pre-authorization call regardless of max_attempts. |
Retry applies only to transient conditions: network errors and 429/502/503/504 responses. Any other error (a non-retryable status, a malformed response body) is returned immediately without retrying. Retry is an availability optimization on top of the fail-open contract below — it reduces how often a transient blip causes this provider to be skipped, but exhausting retries still fails open rather than blocking the request.
The http enrichment provider is fail-open — an outage or bad response degrades to the original, un-enriched operation/resource rather than blocking the request. This is the opposite of the fail-closed HTTP Provider used for MPE/PDP authorization. See Authorization Enrichment concepts for the full request/response wire protocol.
See Authorization Enrichment for the full guide.
Debug Logging
AGENTVISOR_LOG_LEVEL=info,mcp=debug agentvisor serve ./my-agent
See MCP Gateway Guide for architecture and security details.
A2A Gateway
The A2A Gateway allows agents to communicate with external A2A-compatible agents using Google's Agent-to-Agent protocol (JSON-RPC 2.0 with SSE streaming).
This section documents the A2A Gateway (agents → external A2A agents). To expose agents via
A2A protocol to external clients, see API Transports and enable
api.a2a.enabled.
Connection Pool & Defaults
| Env var | Description |
|---|---|
AGENTVISOR_A2A_GATEWAY_POOL_IDLE_TIMEOUT | Close idle principal-bound A2A connections after this duration |
AGENTVISOR_A2A_GATEWAY_POOL_MAX_SIZE | Maximum connections in the principal-bound A2A LRU pool |
AGENTVISOR_A2A_GATEWAY_DEFAULTS_TIMEOUT | Default request timeout for A2A agent calls |
AGENTVISOR_A2A_GATEWAY_DEFAULTS_RETRY_INITIAL_INTERVAL | Initial backoff between A2A retry attempts (exponential backoff) |
AGENTVISOR_A2A_GATEWAY_DEFAULTS_RETRY_MAX_ATTEMPTS | Maximum retry attempts for A2A requests |
AGENTVISOR_A2A_GATEWAY_DEFAULTS_RETRY_MAX_INTERVAL | Maximum backoff between A2A retry attempts |
a2a_gateway:
defaults:
retry:
initial_interval: "1s"
max_attempts: 3
max_interval: "30s"
timeout: "1m"
log_level: "summary"
on_connect_failure: "fail"
pool:
idle_timeout: "5m"
max_size: 100
Startup Failure Posture
| Env var | Config key | Default | Description |
|---|---|---|---|
AGENTVISOR_A2A_GATEWAY_ON_CONNECT_FAILURE | a2a_gateway.on_connect_failure | fail | Behavior when a static (non-principal-bound) A2A agent fails to connect at startup. fail aborts startup; warn logs a warning and continues in a degraded state — the degraded status and failure counts are always visible via GET /ready regardless of this setting, while failed agent names and failure classes are only disclosed to an authorized principal. |
Audit Logging
| Env var | Config key | Default | Description |
|---|---|---|---|
AGENTVISOR_A2A_GATEWAY_LOG_LEVEL | a2a_gateway.log_level | summary | Verbosity of A2A gateway call audit logging: none, summary, full. Independent of both AGENTVISOR_LOG_LEVEL and mcp.log_level — mirrors the guest.proxy.log_level split between severity and audit detail. |
a2a_gateway:
log_level: summary # none | summary | full
Agent Configuration
A2A agents are configured in the YAML file only (a2a_gateway.agents[]):
| Field | Required | Description |
|---|---|---|
name | Yes | Unique identifier (used in SDK calls) |
url | Yes | A2A agent endpoint URL |
credentials | No | Authentication configuration (same types as MCP) |
timeout | No | Per-agent timeout override |
retry | No | Per-agent retry override |
enrichment | No | Authz enrichment (rego or http provider) |
tls | No | Outbound TLS trust configuration for url |
a2a_gateway:
agents:
- name: research-agent
url: "https://research.example.com/a2a"
credentials:
type: bearer_token
source: env
env_var: RESEARCH_AGENT_TOKEN
timeout: 120s
- name: internal-agent
url: "https://internal.example.com/a2a"
credentials:
type: principal_passthrough
# tls: # Optional: trust a private CA for url
# mode: verify-ca
# ca_file: /etc/ssl/internal-agent-ca.pem
a2a_gateway.agents[].tls configures outbound trust for the connection to
that agent's url (e.g. tls.ca_file to trust a private CA). See
TLS Trust Configuration for the
full field reference.
Task States
| State | Description |
|---|---|
working | Task is in progress |
input_required | Task needs additional input from the caller |
auth_required | Task requires authentication |
completed | Task finished successfully |
failed | Task failed with an error |
canceled | Task was canceled |
rejected | Task was rejected by the agent |
See A2A Gateway Guide for usage examples and SDK integration.
Telemetry
OpenTelemetry distributed tracing and Prometheus metrics.
| Env var | Description |
|---|---|
AGENTVISOR_TELEMETRY_ENVIRONMENT | Deployment environment tag (e.g. development, production) |
AGENTVISOR_TELEMETRY_SERVICE_NAME | OTLP service.name resource attribute for the host process |
telemetry:
environment: "development"
service_name: "agentvisor-host"
Tracing
| Env var | Description |
|---|---|
AGENTVISOR_TELEMETRY_TRACING_ENABLED | Enable OTLP trace export |
AGENTVISOR_TELEMETRY_TRACING_ENDPOINT | OTLP collector endpoint; for gRPC: host:port; for HTTP: URL with path |
AGENTVISOR_TELEMETRY_TRACING_HEADERS | Custom HTTP headers for OTLP/HTTP export; used for authentication (e.g. Langfuse). Config file only (YAML map) -- this env var is not bound |
AGENTVISOR_TELEMETRY_TRACING_PROTOCOL | OTLP transport: grpc (default) or http |
AGENTVISOR_TELEMETRY_TRACING_SAMPLE_RATE | Trace sampling rate from 0.0 (none) to 1.0 (all) |
AGENTVISOR_TELEMETRY_TRACING_TLS_CA_DATA | Base64-encoded PEM CA certificate for verifying the OTLP collector (alternative to ca_file) |
AGENTVISOR_TELEMETRY_TRACING_TLS_CA_FILE | Path to PEM CA certificate for verifying the OTLP collector |
AGENTVISOR_TELEMETRY_TRACING_TLS_CERT_DATA | Base64-encoded PEM client certificate for mTLS to the collector (alternative to cert_file) |
AGENTVISOR_TELEMETRY_TRACING_TLS_CERT_FILE | Path to PEM client certificate for mTLS authentication to the collector |
AGENTVISOR_TELEMETRY_TRACING_TLS_KEY_DATA | Base64-encoded PEM client private key for mTLS to the collector (alternative to key_file) |
AGENTVISOR_TELEMETRY_TRACING_TLS_KEY_FILE | Path to PEM client private key for mTLS authentication to the collector |
AGENTVISOR_TELEMETRY_TRACING_TLS_MODE | TLS verification mode: verify-full (default), verify-ca, require, or disable — an unset mode defaults to verify-full |
AGENTVISOR_TELEMETRY_TRACING_TLS_SERVER_NAME | TLS SNI server name override |
AGENTVISOR_TELEMETRY_TRACING_TLS_TRUST_SYSTEM_ROOTS | Append the configured CA to the system root pool instead of replacing it (default: false) |
telemetry:
tracing:
enabled: false
endpoint: "localhost:4317"
headers: {}
protocol: "grpc"
sample_rate: 1
tls:
ca_data: ""
ca_file: ""
cert_data: ""
cert_file: ""
key_data: ""
key_file: ""
mode: ""
server_name: ""
trust_system_roots: false
Metrics
| Env var | Description |
|---|---|
AGENTVISOR_TELEMETRY_METRICS_ENABLED | Enable Prometheus metrics endpoint |
AGENTVISOR_TELEMETRY_METRICS_ENDPOINT | HTTP path for the Prometheus metrics endpoint |
telemetry:
metrics:
enabled: false
endpoint: "/metrics"
Trace Propagation
| Env var | Description |
|---|---|
AGENTVISOR_TELEMETRY_PROPAGATION_INPUT | Trace context formats to extract from incoming requests (comma-separated): tracecontext, baggage, b3, b3multi, jaeger, xray |
AGENTVISOR_TELEMETRY_PROPAGATION_OUTPUT | Trace context formats to inject into outgoing requests (comma-separated): tracecontext, baggage, b3, b3multi, jaeger, xray |
telemetry:
propagation:
input:
- tracecontext
- baggage
output:
- tracecontext
- baggage
Agent Span Forwarding
| Env var | Description |
|---|---|
AGENTVISOR_TELEMETRY_AGENT_TRACING_ENABLED | Forward OTLP spans from agents to the host exporter |
AGENTVISOR_TELEMETRY_AGENT_TRACING_SERVICE_NAME_TEMPLATE | Template for service.name on forwarded agent spans; supports {agent_name} (empty = preserve original) |
telemetry:
agent_tracing:
enabled: true
service_name_template: ""
Langfuse Example
telemetry:
service_name: agentvisor-host
environment: production
tracing:
enabled: true
protocol: http
endpoint: https://cloud.langfuse.com/api/public/otel
headers:
Authorization: "Basic <base64(publicKey:secretKey)>"
agent_tracing:
enabled: true
service_name_template: "agent-{agent_name}"
gVisor Syscall Tracing
gVisor syscall tracing provides visibility into agent behavior for security monitoring, debugging,
and compliance. Only applies to the gvisor sandbox mode.
See Runtime Tracing for architecture details and Security Monitoring Guide for operational guidance.
| Env var | Description |
|---|---|
AGENTVISOR_TRACE_CATEGORIES | Preset syscall groups to trace (comma-separated): file_access, process, network, identity, filesystem |
AGENTVISOR_TRACE_CONTEXT_FIELDS | gVisor context fields to include in events: container_id, process_name, credentials, cwd |
AGENTVISOR_TRACE_ENABLED | Enable gVisor syscall tracing for security monitoring and observability |
AGENTVISOR_TRACE_OPTIONAL_FIELDS | Expensive optional fields to include in events: fd_path (resolves file descriptors to paths) |
AGENTVISOR_TRACE_SYSCALLS | Explicit list of syscalls to trace (alternative to categories; comma-separated) |
trace:
categories:
- file_access
- process
context_fields: []
enabled: false
optional_fields: []
syscalls: []
Trace Categories
| Category | Description |
|---|---|
file_access | File open, read, write, close operations |
process | Process creation, execution, exit |
network | Socket operations, connections |
identity | User/group ID operations |
filesystem | Mount, unmount, filesystem metadata |
Event Buffer
| Env var | Description |
|---|---|
AGENTVISOR_TRACE_BUFFER_DROP_POLICY | Action when the trace event buffer is full: oldest (drop oldest), newest (drop new), or block |
AGENTVISOR_TRACE_BUFFER_SIZE | Trace event ring buffer capacity (number of events) |
trace:
buffer:
drop_policy: "oldest"
size: 10000
| Drop Policy | Description |
|---|---|
oldest | Drop oldest events when buffer is full (default) |
newest | Drop new events when buffer is full |
block | Block until space is available (may impact agent performance) |
Classification Rules (Rego)
| Env var | Description |
|---|---|
AGENTVISOR_TRACE_RULES_ENABLED | Enable Rego-based event classification engine for trace events |
AGENTVISOR_TRACE_RULES_POLICY_FILES | Paths to Rego policy files for trace event classification (comma-separated) |
AGENTVISOR_TRACE_RULES_POLICY_INLINE | Inline Rego policy string for trace event classification |
AGENTVISOR_TRACE_RULES_USE_DEFAULT_POLICY | Load the built-in default classification policy when the Rego rules engine is enabled |
trace:
rules:
enabled: false
policy_files: []
policy_inline: ""
use_default_policy: true
Log, Metrics & OTEL Sinks
| Env var | Description |
|---|---|
AGENTVISOR_TRACE_SINKS_LOG_ENABLED | Enable structured log sink for trace events |
AGENTVISOR_TRACE_SINKS_LOG_LEVEL | Minimum severity level for log sink output: debug, info, warn, or error |
AGENTVISOR_TRACE_SINKS_METRICS_ENABLED | Enable Prometheus metrics sink for trace event counts |
AGENTVISOR_TRACE_SINKS_OTEL_ENABLED | Enable OpenTelemetry trace sink (exports trace events as OTEL spans) |
gRPC Streaming Sink
| Env var | Description |
|---|---|
AGENTVISOR_TRACE_SINKS_GRPC_BUFFER_SIZE | Event buffer size for the gRPC trace sink (handles network hiccups) |
AGENTVISOR_TRACE_SINKS_GRPC_ENABLED | Enable gRPC streaming sink for real-time trace event consumers |
AGENTVISOR_TRACE_SINKS_GRPC_ENDPOINT | gRPC server address for streaming trace events (e.g. collector.example.com:9090) |
AGENTVISOR_TRACE_SINKS_GRPC_MAX_RECONNECT_BACKOFF | Maximum backoff between gRPC trace sink reconnection attempts |
AGENTVISOR_TRACE_SINKS_GRPC_RECONNECT_INTERVAL | Initial wait before reconnecting the gRPC trace sink after a failure |
AGENTVISOR_TRACE_SINKS_GRPC_TLS_CA_DATA | Base64-encoded PEM CA certificate for verifying the gRPC trace sink server (alternative to ca_file) |
AGENTVISOR_TRACE_SINKS_GRPC_TLS_CA_FILE | Path to PEM CA certificate for verifying the gRPC trace sink server |
AGENTVISOR_TRACE_SINKS_GRPC_TLS_CERT_DATA | Base64-encoded PEM client certificate for mTLS to the gRPC trace sink (alternative to cert_file) |
AGENTVISOR_TRACE_SINKS_GRPC_TLS_CERT_FILE | Path to PEM client certificate for mTLS authentication to the gRPC trace sink |
AGENTVISOR_TRACE_SINKS_GRPC_TLS_KEY_DATA | Base64-encoded PEM client private key for mTLS to the gRPC trace sink (alternative to key_file) |
AGENTVISOR_TRACE_SINKS_GRPC_TLS_KEY_FILE | Path to PEM client private key for mTLS authentication to the gRPC trace sink |
AGENTVISOR_TRACE_SINKS_GRPC_TLS_MODE | TLS verification mode: verify-full, verify-ca, require, or disable. Unset with no other TLS options means TLS is off. require needs AGENTVISOR_TLS_ALLOW_INSECURE=true |
AGENTVISOR_TRACE_SINKS_GRPC_TLS_SERVER_NAME | TLS SNI server name override for the gRPC trace sink |
AGENTVISOR_TRACE_SINKS_GRPC_TLS_TRUST_SYSTEM_ROOTS | Append the configured CA to the system root pool instead of replacing it (default: false) |
AGENTVISOR_TRACE_SINKS_GRPC_AUTH_ENV_VAR | Environment variable containing the bearer token for gRPC trace sink authentication |
AGENTVISOR_TRACE_SINKS_GRPC_AUTH_TYPE | Authentication for the gRPC trace sink: none or bearer_token |
trace:
sinks:
grpc:
auth:
env_var: ""
type: "none"
buffer_size: 1000
enabled: false
endpoint: ""
max_reconnect_backoff: "1m"
reconnect_interval: "5s"
tls:
ca_data: ""
ca_file: ""
cert_data: ""
cert_file: ""
key_data: ""
key_file: ""
mode: ""
server_name: ""
trust_system_roots: false
Webhook Sink
| Env var | Description |
|---|---|
AGENTVISOR_TRACE_SINKS_WEBHOOK_BATCH_SIZE | Number of events to batch before sending to the webhook endpoint |
AGENTVISOR_TRACE_SINKS_WEBHOOK_ENABLED | Enable webhook sink for streaming trace events to SIEM or security dashboards |
AGENTVISOR_TRACE_SINKS_WEBHOOK_FLUSH_INTERVAL | Maximum time to wait before flushing a partial batch to the webhook |
AGENTVISOR_TRACE_SINKS_WEBHOOK_HEADERS | Custom HTTP headers for webhook requests. Config file only (YAML map) -- this env var is not bound; values are used verbatim, with no ${VAR} substitution |
AGENTVISOR_TRACE_SINKS_WEBHOOK_TIMEOUT | HTTP request timeout for webhook deliveries |
AGENTVISOR_TRACE_SINKS_WEBHOOK_URL | Webhook endpoint URL for trace event delivery |
AGENTVISOR_TRACE_SINKS_WEBHOOK_RETRY_BACKOFF | Initial backoff for webhook retry attempts (exponential with jitter) |
AGENTVISOR_TRACE_SINKS_WEBHOOK_RETRY_MAX_ATTEMPTS | Maximum retry attempts for failed webhook deliveries |
AGENTVISOR_TRACE_SINKS_WEBHOOK_RETRY_MAX_BACKOFF | Maximum backoff for webhook retry attempts |
AGENTVISOR_TRACE_SINKS_WEBHOOK_TLS_CA_DATA | Base64-encoded PEM CA certificate for verifying the webhook HTTPS endpoint (alternative to ca_file) |
AGENTVISOR_TRACE_SINKS_WEBHOOK_TLS_CA_FILE | Path to PEM CA certificate for verifying the webhook HTTPS endpoint |
AGENTVISOR_TRACE_SINKS_WEBHOOK_TLS_CERT_DATA | Base64-encoded PEM client certificate for mTLS to the webhook endpoint (alternative to cert_file) |
AGENTVISOR_TRACE_SINKS_WEBHOOK_TLS_CERT_FILE | Path to PEM client certificate for mTLS authentication to the webhook endpoint |
AGENTVISOR_TRACE_SINKS_WEBHOOK_TLS_KEY_DATA | Base64-encoded PEM client private key for mTLS to the webhook endpoint (alternative to key_file) |
AGENTVISOR_TRACE_SINKS_WEBHOOK_TLS_KEY_FILE | Path to PEM client private key for mTLS authentication to the webhook endpoint |
AGENTVISOR_TRACE_SINKS_WEBHOOK_TLS_MODE | TLS verification mode: verify-full, verify-ca, require, or disable. Unset with no other TLS options means TLS follows the URL scheme with the default verify-full posture. require needs AGENTVISOR_TLS_ALLOW_INSECURE=true |
AGENTVISOR_TRACE_SINKS_WEBHOOK_TLS_SERVER_NAME | TLS SNI server name override for the webhook endpoint |
AGENTVISOR_TRACE_SINKS_WEBHOOK_TLS_TRUST_SYSTEM_ROOTS | Append the configured CA to the system root pool instead of replacing it (default: false) |
AGENTVISOR_TRACE_SINKS_WEBHOOK_CIRCUIT_BREAKER_ENABLED | Enable circuit breaker protection for the webhook trace sink |
AGENTVISOR_TRACE_SINKS_WEBHOOK_CIRCUIT_BREAKER_FAILURE_THRESHOLD | Consecutive failures before the webhook circuit breaker opens |
AGENTVISOR_TRACE_SINKS_WEBHOOK_CIRCUIT_BREAKER_RESET_TIMEOUT | Wait time before the webhook circuit breaker attempts to close |
trace:
sinks:
webhook:
batch_size: 100
circuit_breaker:
enabled: true
failure_threshold: 5
reset_timeout: "30s"
enabled: false
flush_interval: "5s"
headers: {}
retry:
backoff: "1s"
max_attempts: 3
max_backoff: "30s"
timeout: "10s"
tls:
ca_data: ""
ca_file: ""
cert_data: ""
cert_file: ""
key_data: ""
key_file: ""
mode: ""
server_name: ""
trust_system_roots: false
url: ""
Persistent Store Sink
| Env var | Description |
|---|---|
AGENTVISOR_TRACE_SINKS_STORE_ENABLED | Enable persistent file/SQLite storage sink for trace events (audit trail) |
AGENTVISOR_TRACE_SINKS_STORE_FLUSH_INTERVAL | How often to flush buffered trace events to the store |
AGENTVISOR_TRACE_SINKS_STORE_MAX_FILE_SIZE | Maximum size per trace storage file before rotation (bytes) |
AGENTVISOR_TRACE_SINKS_STORE_PATH | Base directory for persistent trace event storage |
AGENTVISOR_TRACE_SINKS_STORE_PRUNE_INTERVAL | How often to run the retention pruning job for stored trace events |
AGENTVISOR_TRACE_SINKS_STORE_RETENTION | How long to retain stored trace events before automatic pruning |
AGENTVISOR_TRACE_SINKS_STORE_TYPE | Storage backend for trace events: file or sqlite |
trace:
sinks:
store:
enabled: false
flush_interval: "5s"
max_file_size: 104857600
path: "/var/lib/agentvisor/trace"
prune_interval: "1h"
retention: "168h"
type: "file"
Example Configuration
trace:
enabled: true
categories:
- file_access
- process
- network
context_fields:
- container_id
- process_name
sinks:
log:
enabled: true
level: info
metrics:
enabled: true
grpc:
enabled: true
endpoint: "trace-collector.example.com:9090"
tls:
mode: verify-full
ca_file: /etc/agentvisor/trace-ca.crt
AgentVisor Identity
AgentVisor ID provides a unique identifier for this AgentVisor instance, used in:
- Policy Enforcement: Added as the outermost
act.subclaim per RFC 8693 - Telemetry: Used as the OTEL service name
- Logging: Included in all log messages as
agentvisor_id - Authorization Enrichment: Surfaced to enrichment providers as
agentvisor_id(see Authorization Enrichment)
"AgentVisor ID" identifies the AgentVisor instance itself, distinct from the LangGraph Agent
Protocol's agent_id which refers to graph/agent names within the system.
| Env var | Description |
|---|---|
AGENTVISOR_ID_TYPE | AgentVisor instance identity provider: string (literal), env (from environment variable), or empty to disable |
Provider-specific options use env var patterns AGENTVISOR_ID_<TYPE>_<KEY>:
| Variable | Description |
|---|---|
AGENTVISOR_ID_STRING_VALUE | Literal ID value (string provider) |
AGENTVISOR_ID_ENV_VAR | Environment variable name (env provider) |
AGENTVISOR_ID_ENV_DEFAULT | Fallback value when env var is not set (env provider) |
Examples
# Literal string
id:
type: string
string:
value: production-agent-1
# From environment variable
id:
type: env
env:
var: HOSTNAME
default: unknown-agent
RFC 8693 Delegation Chain
When AgentVisor ID is configured, authorization requests include the agent as an actor in the delegation chain:
{
"sub": "user@example.com",
"act": { "sub": "my-agent", "act": {"sub": "api-gateway"} }
}
Analytics
PostHog product analytics are enabled by default in official release builds. Development builds never report.
| Env var | Description |
|---|---|
AGENTVISOR_ANALYTICS_ENABLED | Enable PostHog product analytics; set to false to opt out |
AGENTVISOR_ANALYTICS_ENDPOINT | Custom PostHog ingestion endpoint (empty = PostHog cloud default) |
analytics:
enabled: true
endpoint: ""
What is transmitted
A single runtime_started event is emitted per startup. The event is keyed by a
distinct_id that is an HMAC-SHA256 of the machine hostname (or of the configured
AgentVisor ID when set), keyed by a random secret generated once and persisted under
the cache directory (<cache_dir>/analytics-id.key) — the raw hostname and AgentVisor
ID never leave the process, and without the local key the ID cannot be reversed by
dictionary attack even though hostnames come from a guessable namespace.
Server-side IP geolocation (GeoIP enrichment) is disabled. No security-posture
configuration (authorization provider, API authentication, TLS, or payload-codec
settings) is transmitted, and gateway counts are coarsened into range buckets
(0, 1-5, 6+) rather than exact values.
The complete property list is below. This table is pinned by a test
(TestAnalyticsPayload_MatchesDocumentedPayload), so any change to what is
transmitted must be reflected here.
| Property | Description |
|---|---|
sandbox_mode | Configured sandbox mode (none, docker, gvisor) |
openapi_enabled | Whether the OpenAPI/REST transport is enabled |
mcp_transport_enabled | Whether the MCP transport is enabled |
a2a_transport_enabled | Whether the A2A transport is enabled |
mcp_gateway_servers | Number of configured MCP gateway servers, bucketed (0, 1-5, 6+) |
a2a_gateway_agents | Number of configured A2A gateway agents, bucketed (0, 1-5, 6+) |
telemetry_tracing_enabled | Whether OpenTelemetry tracing is enabled |
telemetry_metrics_enabled | Whether OpenTelemetry metrics are enabled |
store_provider | Configured store backend (sqlite, postgresql, or empty) |
exec_mode | Whether the runtime is in exec mode |
agentvisor_id_configured | Whether an AgentVisor ID is configured (boolean, not the ID itself) |
version | AgentVisor release version |
os | Operating system (GOOS) |
arch | CPU architecture (GOARCH) |
customer_id | Opaque Cryptolens customer record ID (licensed deployments only; never the license key) |
license_id | Opaque Cryptolens license record ID (licensed deployments only; never the license key) |
License
Some AgentVisor distributions require a license key to run.
| Env var | Description |
|---|---|
AGENTVISOR_LICENSE_KEY | License key — set via AGENTVISOR_LICENSE_KEY env var only; rejected if present in YAML |
AGENTVISOR_LICENSE_MACHINE_CODE | Optional machine identifier for node-locked licenses |
AGENTVISOR_LICENSE_STORAGE_BACKEND | Keyring backend: auto, keychain (macOS), secret-service (Linux/GNOME), pass, kwallet, wincred |
AGENTVISOR_LICENSE_STORAGE_SERVICE | Keyring service namespace for scoping entries |
license:
key: ""
machine_code: ""
storage:
backend: "auto"
service: "com.manetu.agentvisor"
OS-native keyring backends are not available inside OCI containers. Always set
AGENTVISOR_LICENSE_KEY as an environment variable in container deployments.
The refresh interval and grace period are baked into the binary at build time and cannot be overridden at runtime.
See Licensing for activation, container deployment patterns, and troubleshooting.
Config File Locations
If AGENTVISOR_CONFIG is set, the host runtime uses that exact file path and skips the default
search. Otherwise, it searches for agentvisor.yaml in:
./agentvisor.yaml(current directory)$HOME/.config/agentvisor/agentvisor.yaml/etc/agentvisor/agentvisor.yaml
Multi-Config Files
AgentVisor supports layered configuration from multiple sources merged in order. This makes it easy to share a base config across environments and override only what differs.
Three mechanisms
| Mechanism | How to use | Error if missing? |
|---|---|---|
| Base config | Default search paths or AGENTVISOR_CONFIG | No (silently skipped) |
conf.d/ fragments | Place .yaml/.yml files in conf.d/ beside the base config | No (directory is optional) |
| Overlay files | --config /path/to/overlay.yaml (repeatable) or AGENTVISOR_CONFIG_FILES=a.yaml,b.yaml | Yes (hard error) |
Merge semantics
- Maps are deep-merged: keys in later configs are added or overridden, other keys are preserved
- Scalars and arrays are replaced entirely by the later value
conf.d/ fragments
AgentVisor automatically scans a conf.d/ directory adjacent to whichever base config file was
found. Files are sorted alphabetically and merged in order after the base config:
./agentvisor.yaml ← base config
./conf.d/
10-temporal.yaml ← merged first
20-authz.yaml ← merged second
50-proxy-credentials.yaml ← merged third
Each fragment only needs to contain the keys it overrides:
# conf.d/10-temporal.yaml
temporal:
target: my-namespace.account-id.tmprl.cloud:7233
namespace: my-namespace.account-id
auth:
type: api_key
--config overlays
--config flags and AGENTVISOR_CONFIG_FILES are two spellings of the same mechanism. The base
config search happens independently — overlays layer on top.
agentvisor serve . --config /etc/agentvisor/temporal-cloud.yaml
AGENTVISOR_CONFIG_FILES is the environment-variable equivalent (comma-separated). When both are
provided, AGENTVISOR_CONFIG_FILES entries come first, then --config flags — so --config
takes precedence.
Overlay files must exist — a missing overlay is a hard error. Use conf.d/ or environment
variables for optional overrides.
Path resolution
Paths in AGENTVISOR_CONFIG_FILES and --config are resolved relative to the current working
directory at startup. Use absolute paths in production and Docker deployments.
Common usage patterns
Docker / Kubernetes:
AGENTVISOR_CONFIG=/etc/agentvisor/base.yaml
AGENTVISOR_CONFIG_FILES=/etc/agentvisor/overlays/temporal-cloud.yaml,/etc/agentvisor/overlays/authz-prod.yaml
Local development:
# ~/.config/agentvisor/agentvisor.yaml sets temporal target and auth
agentvisor serve . --config ./dev-credentials.yaml
Full precedence example
| Source | temporal.target value |
|---|---|
| Built-in default | localhost:7233 |
| Base config | base.tmprl.cloud:7233 |
conf.d/ fragment | confd.tmprl.cloud:7233 |
AGENTVISOR_CONFIG_FILES overlay | envfiles.tmprl.cloud:7233 |
--config overlay | flag.tmprl.cloud:7233 |
AGENTVISOR_TEMPORAL_TARGET env var | envvar.tmprl.cloud:7233 |
The effective value is envvar.tmprl.cloud:7233 — environment variables always win.
Duration Values
Duration values: 30s, 5m, 1h, 1m30s, 100ms.
Proxy Credentials
The HTTP proxy supports symbolic token substitution for secure credential management. Agents use
auto-generated placeholder tokens (e.g., mav-tok-a1b2c3d4e5f6a7b8c9d0e1f2a3b4) which the proxy replaces with
real credentials before making upstream requests. Real credentials never enter the guest sandbox.
How It Works
- Host configuration: Define credential rules with resolvers
- Token generation: Unique tokens are auto-generated at startup
- Guest environment: Tokens are injected as environment variables
- Agent requests: Agent uses the token in HTTP headers (from env var)
- TLS termination: Guest proxy terminates TLS to inspect headers
- Token substitution: Host replaces tokens with real credentials
- Upstream request: Host makes HTTPS request with real API key
Configuration
Proxy credentials are configured in agentvisor.yaml under proxy.credentials
(YAML only — not expressible as flat env vars):
proxy:
credentials:
- name: anthropic-key
guest_env_var: ANTHROPIC_API_KEY # Token auto-injected here
header: "Authorization" # Optional: restrict to specific header
destinations: # Required: restrict to these hostnames
- "api\\.anthropic\\.com" # Regex, auto-anchored for full-match
resolver:
type: bearer_token
source: env
env_var: ANTHROPIC_API_KEY
- name: openai-key
guest_env_var: OPENAI_API_KEY
destinations:
- "api\\.openai\\.com"
resolver:
type: api_key
source: env
env_var: OPENAI_API_KEY
header_name: "Authorization"
- name: internal-api
guest_env_var: INTERNAL_API_TOKEN
destinations:
- "internal\\.example\\.com"
resolver:
type: principal_passthrough
Credential Rule Fields
| Field | Required | Description |
|---|---|---|
name | Yes | Identifier for logging and debugging |
pattern | No | Token pattern (auto-generated: mav-tok-...) |
token_format | No | Format for auto-generated symbolic tokens. {random} expands to 32 random hex characters. Default: mav-tok-{random} |
guest_env_var | No | Env var injected into guest with the token |
header | No | Restrict matching to a specific header (e.g., Authorization) |
destinations | Conditional | Regex patterns matched against request hostname (auto-anchored ^(?:...)$), case-insensitive. Required when resolver.type is set. |
allow_insecure | No | Allow substitution over plaintext http://. Default false — requests must use https:// or the real credential is not substituted. |
resolver | No | Credential resolver configuration (bearer_token, api_key, principal_passthrough, token_exchange, response_intercept). |
Destination Filtering
Destination filtering prevents credential exfiltration — a compromised agent sending a placeholder token to an unauthorized host receives the worthless placeholder, not the real credential.
Patterns are auto-anchored (^(?:...)$) and matched case-insensitively — anthropic\.com
won't match evil-anthropic.com.attacker.com, but does match Anthropic.com.
Matching is on the full origin, not just the hostname: the request must use https:// (unless
the rule sets allow_insecure: true) and the standard port for that scheme (443 for https, 80 for
http) — a non-standard port under a matching hostname never matches, and a plaintext http://
request never receives credentials configured for the https:// endpoint.
Earlier releases matched credential rules on hostname alone. A rule destined for
api\.example\.com used to substitute credentials for https://api.example.com:8443/; it no
longer does — only the scheme-default port (443 for https, 80 for http) matches. If your upstream
listens on a non-standard port, the symbolic token now reaches it as-is, without
substitution, and requests fail authentication at the upstream. There is currently no configuration knob to match a
non-standard port; front the upstream on the standard port (e.g. via a reverse proxy) or expose
it on 443/80 directly.
Resolver Types
| Type | Description | Principal-Bound |
|---|---|---|
bearer_token | Static bearer token from environment variable | No |
api_key | API key injected into custom header | No |
principal_passthrough | Forward caller's JWT to upstream | Yes |
token_exchange | RFC 8693 token exchange for scoped tokens | Yes |
response_intercept | Intercept real tokens in HTTP response bodies and replace with symbolic tokens | No |
Response Interception
Response interception extends credential brokering to HTTP response bodies. When an OAuth token endpoint returns real tokens in a JSON response, AgentVisor replaces them with symbolic tokens before they reach the guest sandbox. The real-to-symbolic mapping is cached host-side for automatic substitution on subsequent requests.
This is useful for OAuth flows (device code, authorization code) where real tokens arrive in response bodies rather than being injected from the host environment.
Use resolver.type: response_intercept on a credential rule. The rule's destinations restricts which hosts are eligible for interception.
credentials:
- name: github-oauth
destinations:
- "github\\.com"
resolver:
type: response_intercept
url_patterns:
- "https://github.com/login/oauth/access_token"
# methods: ["POST"] # Default: POST only
token_fields:
- field: access_token
token_format: "gho_mav{random}"
- field: refresh_token
token_format: "ghr_mav{random}"
Response Intercept Resolver Fields
| Field | Required | Description |
|---|---|---|
type | Yes | Must be response_intercept |
url_patterns | Yes | Glob patterns matched against the request URL path (query string is stripped before matching). * matches a single path segment (no slashes), ** matches any number of segments. Example: https://platform.claude.com/*/oauth/token |
methods | No | HTTP methods to intercept. Default: ["POST"] |
token_fields | Yes | List of JSON fields to intercept in the response body |
token_fields[].field | Yes | Top-level JSON field name (e.g., access_token, refresh_token) |
token_fields[].token_format | No | Symbolic token format. Use {random} for 32 random hex characters. Should mimic the real token prefix to pass client-side validation (e.g., sk-ant-oat01-mav-{random} for Anthropic). Default: mav-tok-{random} |
The intercepted tokens are automatically substituted in both outbound request headers and request bodies. To also broker outbound credentials for the same OAuth flow, add a separate rule with a bearer_token or token_exchange resolver targeting the API's hostname.
Security Notes
- Real credentials never enter the guest sandbox — they stay on the host
- TLS termination uses an ephemeral CA generated at guest startup
- Static credentials are resolved once at startup; principal-bound credentials are resolved per-request
- Destination filtering ensures credentials are only substituted for configured hostnames
Credentials
Global policy settings for credential resolution behavior.
| Env var | Description |
|---|---|
AGENTVISOR_CREDENTIALS_ON_MISSING_ENV_VAR | Startup behavior when a proxy credential env var is missing: fail aborts startup; warn logs a warning and skips the rule |
credentials:
on_missing_env_var: "fail"
Set on_missing_env_var: warn when using a single agentvisor.yaml across dev / staging / prod
stages where some credential env vars are intentionally absent in non-production environments.
Startup succeeds and a structured warning names the missing env var and rule. Rules with a
successfully resolved credential are unaffected.
Environment Variable Index
All AGENTVISOR_* environment variables appear in their concept section alongside the YAML key,
default value, and description. Use your browser's Find (⌘F / Ctrl+F) to search this page
by variable name.
Related Documentation
- API Transports — Overview of transport architecture
- Gateways — Overview of gateway architecture for external service access
- MCP Gateway — Detailed MCP Gateway architecture and security model
- Runtime Tracing — Syscall-level visibility via gVisor seccheck
- MCP Transport Guide — Setting up the MCP Transport for Claude Desktop/Cursor
- A2A Transport Guide — Setting up the A2A Transport for agent interoperability
- Security Monitoring Guide — Operational guide for trace-based security monitoring
- SDK Retry Reference — Python SDK retry configuration and programmatic API