Knowledge baseWorking well

Security model

Project isolation, secret handling, bounded execution, explicit tool permissions, and outbound network rules.

Tenant isolation

Every routine, connection, run, API key, and webhook lookup includes the active project identifier. The API does not trust a project identifier supplied by the caller: it resolves one from the API key, or from a verified session's membership.

A resource belonging to another project returns 404, never 403 — the API does not confirm the existence of something you cannot see.

Secrets

  • API keys are hashed with SHA-256 and shown once, at creation.
  • MCP connection headers, OAuth access tokens, and webhook signing secrets are encrypted at rest with ENCRYPTION_KEY.
  • Connected-model API keys and refreshed provider credentials are encrypted at rest. The API sends them to the private runtime only inside a signed, encrypted, run-scoped envelope; it never returns them to a public client.
  • Encrypted values are never returned by the API, including to their owner.
  • Error messages and execution records are redacted for common secret shapes.
  • Secrets belong in service environment variables, never in tracked files.

The model never receives a credential. Connection headers are resolved server-side at tool-call time and attached to the outbound request, outside the model's context. Connected-model sessions receive only the selected owner's leased credential version; no ambient credentials, CLI login, IDE token, or another account's connection is inherited.

Model and tool execution

Managed model inference goes through LLMGateway. A selected personal ChatGPT, Copilot, or Anthropic model runs through the separate private agent runtime and is never silently rerouted to LLMGateway. Production refuses to start without gateway credentials and refuses to start at all with demo mode enabled.

The full model identity is provider, nullable connection ID, and model ID. Every personal connection is owner-controlled and project-scoped. Catalog and run requests recheck project, owner, provider flag, connection status, and credential version; a stale, missing, revoked, or mismatched value fails closed.

Execution is bounded on three axes:

BoundValue
Idle time per run60–1800 seconds, set per routine
Wall-clock per run30–3600 seconds, set per routine
Authenticated API requestsRate limited per credential in a 60s window
Request body size1 MB on /v1

MCP capabilities are disabled by default, and automatic external tool execution always requires an explicit, tool-specific confirmation. See Tool permissions.

Outbound network rules

Outbound MCP and webhook requests:

  • reject credentials embedded in URLs;
  • do not follow redirects;
  • refuse loopback, link-local, and private or special-use addresses in production; and
  • pin the validated DNS answers to the connection, closing the window where a hostname resolves safely during validation and to an internal address during use.

Webhook deliveries additionally time out after 10 seconds.

Private model-runtime boundary

Production requires TLS on private API-only ingress to one HTTP/1 agent-runtime replica. Requests use signed encrypted envelopes, bounded clocks and sizes, and strict replay/idempotency fields. The runtime does not expose a public provider proxy or accept arbitrary commands, callback URLs, models, tools, or egress destinations.

Every official provider process runs in a mandatory sandbox with a parent-controlled egress proxy. The outer deployment also requires a non-root user, user namespaces, read-only root filesystem, a noexec,nosuid temporary volume, and health/readiness probes. Direct DNS and direct internet are denied; the Work on Repeat tool callback is a separate run-scoped loopback capability with an unpredictable bearer token and an exact allowlisted tool name.

Temporary roots, sockets, mounts, reverse-capability tokens, and supervised processes are owned per operation and cleaned after success, failure, timeout, cancel, and shutdown. Operators verify owner/mode/age and counts only. They do not open, print, copy, hash, archive, or inspect credential/work-file contents to prove cleanup.

Logging, analytics, and privacy evidence

Ingress and runtime logs allow fixed categories, request/run IDs, safe counters, timings, capacity, and cleanup outcomes. They exclude headers, cookies, OAuth state/codes, API keys, encrypted envelopes, account details, prompts, provider bodies/errors, tool content, and temporary-root contents. A development-only log exclusion is not evidence that production ingress logging is safe.

Dashboard browser evidence used a guarded test-only PostHog automation admission after confirming webdriver=true and that the default user-agent filter rejected the browser. Production bot filtering, consent, masking, and body/header capture configuration were unchanged. The test separately scanned loaded SDK recording/timing plus owned public artifacts; cleaned private compiler, SQLite, runtime, and process roots were checked by bounded ownership and cleanup assertions. Scanning public artifacts does not prove every private byte was scanned.

This evidence is local fake-provider privacy evidence. It is not production PostHog-account configuration, default bot-filter verification, deployed ingress telemetry, native provider execution, or live-account proof.

Webhook authenticity

Payloads are signed with HMAC-SHA256 over `${timestamp}.${rawBody}` using a per-routine secret. Consumers should validate the timestamp against a replay window, compute the signature over the unmodified body, and compare in constant time. See Receive run webhooks.

Your responsibilities

Work on Repeat bounds what a routine can do. What it should do is yours:

On this page

Edit this page on GitHub