Skip to main content

Vengtoo Agent

The Vengtoo Agent runs on your infrastructure. It pulls your tenant's policy bundle from Vengtoo cloud on a configurable interval (default: 30 seconds), evaluates it in-memory, and answers POST /access/v1/evaluation requests locally.

Why run the agent

  • Low latency — decisions are evaluated in-memory locally, with no network round-trip to the cloud.
  • Data stays local — decision inputs never leave your network.
  • Graceful degradation — if the cloud is unreachable, the agent keeps serving from the last cached bundle.
  • No code changes — point any SDK at the agent with a single baseUrl config; the evaluation API is identical to cloud.

Architecture

Vengtoo Cloud Your Infrastructure
+-------------------------+ +---------------------------+
| Vengtoo Cloud | bundle | Vengtoo Agent |
| GET /v1/policies/ | (tar.gz) | |
| bundle | ─────────► | - in-memory evaluation |
+-------------------------+ every | - disk-cached bundle |
30s | - localhost:8181 |
+-------------+-------------+

POST /access/v1/evaluation

+-------------v-------------+
| Your service |
+---------------------------+

On restart, the agent loads the cached bundle from disk and starts serving immediately — without waiting for the next cloud sync.

Feature scope

The agent always contacts Vengtoo Cloud to pull its policy bundle — that connection is how policies stay current. What changes when you route evaluation calls to the agent (localhost:8181) instead of the cloud endpoint is which features are enforced at decision time.

RBAC, ABAC, direct grants, and policy modifiers are baked into the bundle and evaluated fully in-memory on the agent. The following features are only enforced when evaluation goes through the cloud endpoint (api.vengtoo.com/access/v1/evaluation) — they have no effect when calling the local agent:

FeatureCloud endpointLocal agent endpoint
RBAC / ABAC / direct grants
Policy modifiers (time window, IP allowlist)
Agent-to-agent delegation— Delegation records are live DB state
Human-in-the-loop approval— Approval state changes on human action
Rate limiting— Per-subject counters require shared state
JIT subject creation— Writes to the entity DB

The agent still forwards decision events to the cloud audit log when reachable (VENGTOO_AUDIT_FORWARDING=true, the default). Set it to false to suppress forwarding entirely.

If you need delegation chains or human-in-the-loop approval enforced on the local evaluation path — for example, in an air-gapped deployment — contact us about Enterprise private-PDP options.

Install

Binary

Download the latest release from GitHub Releases for your platform (linux/amd64, linux/arm64, darwin/arm64).

Go install

go install github.com/vengtoo/agent/cmd/agent@latest

Docker

Image: vengtoo/agent on Docker Hub.

docker pull vengtoo/agent:latest
docker run -d \
--name vengtoo-agent \
-e VENGTOO_API_KEY=azx_... \
-p 8181:8181 \
-v vengtoo-cache:/var/lib/vengtoo/bundles \
-e VENGTOO_CACHE_DIR=/var/lib/vengtoo/bundles \
vengtoo/agent:latest

Docker Compose

services:
vengtoo-agent:
image: vengtoo/agent:latest
environment:
VENGTOO_API_KEY: ${VENGTOO_API_KEY}
VENGTOO_CACHE_DIR: /var/lib/vengtoo/bundles
volumes:
- vengtoo-cache:/var/lib/vengtoo/bundles
ports:
- "8181:8181"

volumes:
vengtoo-cache:

Mount a persistent volume at VENGTOO_CACHE_DIR so the agent can warm-start across container replacements.

Configuration

The agent resolves configuration in this order:

  1. --config <path> — explicit path passed as a CLI flag
  2. ./vengtoo-agent.yaml — current working directory
  3. $HOME/.vengtoo/agent.yaml — home directory fallback

Environment variables override whichever YAML file was loaded.

Env varYAML keyDefaultPurpose
VENGTOO_API_KEYapi_key— (required)Bearer token sent to the cloud policy bundle endpoint.
VENGTOO_CLOUD_URLcloud_urlhttps://api.vengtoo.comCloud base URL. Override for staging or self-hosted.
VENGTOO_TENANT_IDtenant_idauto-resolvedUsually inferred from the bundle. Set explicitly for multi-tenant bundles.
VENGTOO_LISTEN_ADDRlisten_addr0.0.0.0:8181HTTP listen address.
VENGTOO_POLL_INTERVALpoll_interval30sGo time.Duration. Bundle re-pull frequency.
VENGTOO_CACHE_DIRcache_dir~/.vengtoo/bundlesWhere bundle.json is persisted.
VENGTOO_LOG_LEVELlog_levelinfoLog level.
VENGTOO_DECISION_LOGdecision_logfalseSet to true to emit a JSON log line per decision.
VENGTOO_AGENT_NAMEagent_namehostnameIdentifies this agent instance in the dashboard. Defaults to os.Hostname(). Set explicitly when running multiple agents in the same tenant.
VENGTOO_AUDIT_FORWARDINGaudit_forwardingtrueForwards decisions to cloud for the Decision Log. Set to false to disable.
VENGTOO_CLIENT_SECRETclient_secret— (optional)When set, requires Authorization: Bearer <secret> on /access/v1/evaluation. /healthz and /readyz stay open.
VENGTOO_AGENT_REGIONagent_regionDisplay label for the region this agent runs in. Shown in the dashboard.
VENGTOO_AGENT_DOMAINagent_domainDisplay label for the domain or environment (e.g. prod, staging). Shown in the dashboard.
VENGTOO_HEARTBEAT_INTERVALheartbeat_interval30sHow often the agent sends a liveness ping to cloud.
VENGTOO_AUDIT_ENDPOINTaudit_endpointderived from cloud_urlOverride the endpoint where decision events are forwarded. Defaults to <cloud_url>/v1/agent-logs/ingest.
VENGTOO_AUDIT_BATCH_SIZEaudit_batch_size100Number of decision events to buffer before flushing to cloud.
VENGTOO_AUDIT_BATCH_INTERVALaudit_batch_interval5sMaximum time to wait before flushing a partial batch.
VENGTOO_AUDIT_BUFFER_SIZEaudit_buffer_size10000In-memory buffer capacity for decision events. Events are dropped if the buffer fills.
VENGTOO_AUDIT_RETRY_ATTEMPTSaudit_retry_attempts5Number of retry attempts for failed audit log flushes.
VENGTOO_TRUSTED_KEYS_PATHtrusted_keys_path~/.vengtoo/trusted_keys.jsonPath to a pinned public keys file for bundle signature verification in air-gapped environments.

All variables are prefixed VENGTOO_.

Example vengtoo-agent.yaml:

api_key: "azx_..."
cloud_url: "https://api.vengtoo.com"
listen_addr: "0.0.0.0:8181"
poll_interval: "30s"
cache_dir: "/var/lib/vengtoo/bundles"
decision_log: true

Using with SDKs

Point any SDK at the agent:

client := vengtoo.NewClient("", vengtoo.WithBaseURL("http://localhost:8181"))

No API key is needed on calls to the agent — the agent authenticates with cloud on your behalf to fetch bundles.

Health endpoints

EndpointPurpose
GET /healthzDiagnostic JSON: bundle revision, last sync time, degraded flag, consecutive failures, sync age. Returns 200 while the process is up, even when stale.
GET /readyz200 once a bundle has loaded (from cache or cloud). 503 during the cold-start window. Use this as your orchestrator readiness probe.

Example /healthz body:

{
"status": "ok",
"bundle_revision": "a3f8c2d1",
"last_sync": "2026-04-19T14:02:41Z",
"degraded": false,
"consecutive_failures": 0,
"sync_age_seconds": 12.4
}

Metrics

GET /metrics exposes Prometheus-format metrics.

MetricTypeLabelsMeaning
vengtoo_agent_upgauge1 while the process is alive.
vengtoo_agent_decisions_totalcounterallowed, access_pathOne per /access/v1/evaluation call.
vengtoo_agent_decision_duration_secondshistogramallowedEval latency. Buckets tuned for sub-ms.
vengtoo_agent_bundle_last_sync_timestamp_secondsgaugeUnix ts of last successful sync.
vengtoo_agent_bundle_sync_failures_totalcounterMonotonic count of failed bundle polls.
vengtoo_agent_bundle_cache_hitcountersource (cache / sync)How the agent became ready at startup.
vengtoo_agent_degradedgauge1 when serving stale data because cloud sync is failing.
vengtoo_agent_consecutive_sync_failuresgaugeCurrent sync failure streak. Resets on success.

Recommended alerts:

  • vengtoo_agent_up == 0 — process is down.
  • vengtoo_agent_degraded == 1 for more than 5 minutes — sustained cloud unreachability.
  • time() - vengtoo_agent_bundle_last_sync_timestamp_seconds > 600 — no successful sync in 10 minutes.

Decision logs

Set VENGTOO_DECISION_LOG=true to emit one JSON line to stdout per /access/v1/evaluation call:

{
"time": "2026-04-19T14:03:11.482Z",
"level": "INFO",
"msg": "decision",
"subject_id": "a5f77b72-d139-46e7-b3f2-09dfe049bedc",
"resource_id": "14d9ce16-dea0-4de4-b528-ef5949ef9614",
"action": "view",
"decision": true,
"reason": "Access granted via role",
"access_path": "role",
"policy_id": "550e8400-e29b-41d4-a716-446655440000",
"ms": 0.42
}

Tail them live:

docker logs -f vengtoo-agent | grep '"msg":"decision"'

Volume can be high under load, and subject/resource attributes may contain PII — leave this off in production by default. Pipe through Datadog, Loki, CloudWatch, or any structured-log collector as needed.

Graceful degradation

On every startup, the agent does two things in order:

  1. Load from disk cache — if bundle.json exists in VENGTOO_CACHE_DIR, the agent starts serving decisions immediately. /readyz goes 200 before any network call.
  2. Sync with cloud — pulls a fresh bundle and replaces the in-memory engine on revision bump.

If the cloud is unreachable, the agent continues serving from the cached bundle. The following signal the degraded state:

  • /healthz"degraded": true, consecutive_failures > 0, sync_age_seconds growing.
  • vengtoo_agent_degraded == 1.
  • Log line at every fifth failure: [ERROR] Bundle sync failing for N consecutive attempts, serving from cache (last successful sync: <age>).

When sync recovers, the agent logs Bundle sync recovered after N consecutive failures, cache refreshed.

If the cloud has never been reached and there is no cached bundle on disk, /readyz stays 503 until the first successful sync.

Trust model

By default the agent trusts anything that can reach :8181 — deploy it inside a Docker network, Kubernetes NetworkPolicy, or VPC with the same isolation guarantees you apply to any internal service.

For stricter isolation, set VENGTOO_CLIENT_SECRET. When set, the agent requires Authorization: Bearer <secret> on every /access/v1/evaluation call and rejects requests without it. Health and readiness probes (/healthz, /readyz) remain open so orchestrators can probe without the secret.

Troubleshooting

SymptomLikely causeCheck
/readyz is 503 after a minuteInitial sync failed and no cache on diskIs VENGTOO_CACHE_DIR mounted? Can the agent reach VENGTOO_CLOUD_URL?
[FATAL] Failed to load config: API key is requiredVENGTOO_API_KEY unsetCheck env vars / mounted config.
vengtoo_agent_degraded == 1 sustainedCloud unreachableVerify outbound connectivity. Logs print last successful sync age at every fifth failure.
Every user sees "permission denied"Wrong tenant bundle, or bundle is stale/healthz → compare bundle_revision with cloud.
[ERROR] Evaluation failed per requestBundle parses but evaluation fails on this input shapeSet VENGTOO_DECISION_LOG=true and capture the failing input.