Zero trust identity and access for AI agents
Octelium is a free and open source, self-hosted zero trust access platform. An agent gets an identity of its own rather than a copy of someone's credentials, reaches resources through a proxy that holds the secrets, has each tool call and each inference request authorized on its own, and leaves an audit trail that names it.
- Free and open source
- Designed for self-hosting
- MCP and LLM gateway modes
kind: User
metadata:
name: release-agent
spec:
type: WORKLOAD
groups:
- agentskind: Policy
metadata:
name: agent-tools
spec:
rules:
- effect: ALLOW
condition:
all:
of:
- match: ctx.request.mcp.method == "tools/call"
- match: ctx.request.mcp.name == "search_docs"
- match: '"agents" in ctx.user.spec.groups'kind: Service
metadata:
name: anthropic
spec:
mode: LLM
isPublic: true
config:
upstream:
url: https://api.anthropic.com
llm:
protocol: ANTHROPIC
auth:
custom:
header: x-api-key
value:
fromSecret: anthropic-api-keyA unified secure access platform
Agents are covered by the same six as everyone else. Each one is described in detail below, in the same order.
- Unified access platform
One architecture for client-based zero-config VPN-like access over WireGuard and QUIC tunnels and clientless access over browsers for humans and OAuth2 access for workloads.
Read more - L7-aware access control
Identity-based, application-layer aware ABAC access control with policy-as-code via CEL and OPA, applied on a per-request basis.
Read more - Secretless access
Dynamic secretless access where teams and AI agents access protected infrastructure without ever holding a credential.
Read more - Unified identity management
Teams, workloads and AI agents share the same model for identity management, access control, and auditing.
Read more - Real-time visibility and auditing
OpenTelemetry-native, real-time, application-layer-aware visibility and structured logging.
Read more - GitOps-friendly management
Octelium is administered like Kubernetes. Define your resources in YAML files, store them in a Git repository.
Read more
One architecture for everything an agent reaches
Each resource an agent uses, whether a model provider, an MCP server, an internal API or a database, is represented by a Service behind an identity-aware proxy. Agents reach them with a client or without one, under the same Policies.
- Clientlessly, the Service URL is what the agent points at, authenticating with standard OAuth2 client credentials or a bearer token, so any language and any HTTP client works without an SDK.
- Over a client-based WireGuard or QUIC tunnel, an agent reaches private resources the same way an engineer does, including SSH servers, databases and Kubernetes clusters a browser cannot speak to.
- MCP servers can run anywhere, including as containers the Cluster deploys, scales and serves itself from a public or private registry.
kind: Service
metadata:
name: tools-mcp
spec:
mode: MCP
isPublic: true
config:
upstream:
url: http://mcp.internal:8080
mcp:
endpoint: /mcpkind: Service
metadata:
name: pg-staging
spec:
mode: POSTGRES
port: 5432
config:
upstream:
url: postgres://10.0.4.40:5432
postgres:
user: agent_ro
database: staging
auth:
password:
fromSecret: pg-staging-passwordkind: Service
metadata:
name: tools-mcp
spec:
mode: MCP
isPublic: true
config:
upstream:
container:
port: 8080
image: ghcr.io/acme/mcp:1.4.0
replicas: 2
mcp:
endpoint: /mcpLayer-7 aware access control with policy-as-code
Access is authorized on a per-request basis, using CEL or Open Policy Agent, against the identity behind the request and the content of the request itself. For an agent that means the tool it is calling and the model it is asking for, not merely the endpoint it reached.
- MCP context covers the protocol version, the JSON-RPC method, the tool, prompt or resource name, and the parsed request body including tool arguments.
- LLM context covers the protocol, operation, requested model, streaming flag, declared tools and tool names, input modalities and the declared output-token maximum.
- Independently of policy, the gateways enforce limits on request size, streamed event size, estimated input tokens, declared output tokens and declared tool count.
kind: Policy
metadata:
name: read-only-tools
spec:
rules:
- effect: ALLOW
condition:
all:
of:
- match: ctx.request.mcp.method == "tools/call"
- match: ctx.request.mcp.name == "search_docs"
- match: '"agents" in ctx.user.spec.groups'
- effect: ALLOW
condition:
match: ctx.request.mcp.method == "tools/list"kind: Policy
metadata:
name: agent-models
spec:
rules:
- effect: ALLOW
condition:
all:
of:
- match: ctx.request.llm.operation == "MESSAGES"
- match: ctx.request.llm.maxOutputTokens <= 4096
- match: '"agents" in ctx.user.spec.groups'kind: Service
metadata:
name: anthropic
spec:
mode: LLM
config:
upstream:
url: https://api.anthropic.com
llm:
protocol: ANTHROPIC
limits:
maxRequestBytes: 8388608
maxEstimatedInputTokens: 100000
maxOutputTokens: 8192
maxTools: 64Credentials an agent never holds
Application-layer credentials are stored in the Cluster as Secrets and injected into the upstream connection once a request is authorized. This is the part of the problem that grows fastest with agentic systems, because the number of non-human identities holding credentials grows faster than the number of people.
- Covers model provider API keys, MCP upstream tokens, HTTP API keys and access tokens, SSH passwords and private keys, database passwords, kubeconfigs and mTLS client certificates.
- Downstream Authorization, X-Api-Key and Api-Key credentials are removed before proxying, so an agent's own token is never forwarded to a model provider or an MCP server.
- Which upstream, account and credential are used can be selected per request from identity and context, so a release agent and a research agent share a Service URL with different rights.
kind: Service
metadata:
name: openai
spec:
mode: LLM
isPublic: true
config:
upstream:
url: https://api.openai.com
llm:
protocol: OPENAI
auth:
bearer:
fromSecret: openai-api-keykind: Service
metadata:
name: tools-mcp
spec:
mode: MCP
isPublic: true
config:
upstream:
url: https://mcp.example.com
mcp:
endpoint: /mcp
auth:
bearer:
fromSecret: mcp-upstream-tokenkind: Service
metadata:
name: tools-mcp
spec:
mode: MCP
config:
upstream:
url: http://general-mcp:8080
mcp:
endpoint: /mcp
dynamicConfig:
configs:
- name: privileged
upstream:
url: http://admin-mcp:8080
mcp:
auth:
bearer:
fromSecret: admin-mcp-token
rules:
- condition:
match: '"release" in ctx.user.spec.groups'
configName: privilegedA unified identity model for humans and workloads
Human and workload Users share the same identity management, authentication, access control and visibility model. An agent is not a separate system to administer, and it is not a person's session being reused by a program.
- Agents authenticate secretlessly with federated OIDC assertions from GitHub Actions, cloud providers and Kubernetes clusters, or with authentication tokens and OAuth2 client credentials.
- A workload User declares which external identity may authenticate as it, so an assertion issued for one repository is not interchangeable with one issued for another.
- There is no notion of an admin or superuser User, so an agent carries no standing privilege by default, and access requests with approvals cover elevation where it is needed.
- Cordium, built on Octelium, provides isolated sandboxes for agents and developers, where processes reach authorized Services through the Workspace identity with no secrets inside the sandbox.
kind: IdentityProvider
metadata:
name: github-actions
spec:
oidcIdentityToken:
issuerURL: https://token.actions.githubusercontent.com
audience: https://example.comkind: User
metadata:
name: release-agent
spec:
type: WORKLOAD
groups:
- agents
authentication:
identities:
- identityProvider: github-actions
identifier: repo:acme/apiocteliumctl create cred \
--type oauth2 \
--user release-agent \
agent-cred
# The agent then authenticates at
# https://<DOMAIN>/oauth2/token
# and sends the issued bearer access token.What the agent called, and what it cost
Every request produces an AccessLog identifying the User and Session alongside the application-layer detail of the request itself, emitted in real time to your OpenTelemetry OTLP receivers.
- MCP entries include the protocol version, method, target name, request identifier, client information, result type and tool error status, with request and response bodies captured by default.
- LLM entries include the operation, requested and returned model, finish reason, time to first token and provider-reported input, output, cached and reasoning token usage.
- Logs are exported over OpenTelemetry OTLP in real-time to SIEM providers you already operate.
A scalable platform that also deploys your workloads
A Cluster runs on Kubernetes and uses it to scale its own data plane, place Service proxies across Gateways, and run containerized applications that the Cluster itself deploys.
- Managed containers deploy, scale and serve containerized MCP servers and inference servers as Service upstreams, with resource limits, volumes and health probes.
- The Cluster is managed declaratively. Agents, their groups, their Policies and the Services they reach are all YAML in a Git repository, applied with a single octeliumctl apply.
- Management is centralized over the Cluster's gRPC APIs, so provisioning and revoking an agent can itself be automated.
$ octeliumctl apply ./cluster
Secret: anthropic-api-key Updated
Secret: mcp-upstream-token Updated
IdentityProvider: github-actions Created
Policy: agent-tools Created
Group: agents Created
User: release-agent Created
Service: tools-mcp.ai Created
Service: anthropic.ai Created
Service: pg-staging.db Updated
Namespace: ai Created
Cluster Core resources successfully applied
7 resources created
3 resources updated
ClusterConfig updatedWhat an autonomous agent needs, and what issues it
An agent that can act on real systems needs the same things a new employee needs, on a shorter timescale and in larger numbers. These are the requirements, next to the mechanism in an Octelium Cluster that provides each one.
- 01
An identity of its own
An agent is a workload User, not a shared service account and not a copy of a person's session. It has its own groups, its own Policies, its own Session and its own entries in the audit trail, which is what makes revoking one agent a contained action.
Read more - 02
A way to prove that identity without a stored secret
Agents authenticate with federated OpenID Connect assertions issued by the platform running them, such as GitHub Actions, a cloud provider or a Kubernetes cluster, so no long-lived token has to sit in the environment they run in. Authentication tokens and OAuth2 client credentials remain available where assertions are not.
Read more - 03
Access to resources it never holds credentials for
Upstream credentials stay in the Cluster and are injected after a request is authorized, which covers HTTP API keys, SSH passwords and private keys, database passwords, kubeconfigs and mTLS certificates. A prompt injection cannot exfiltrate a credential the agent never had.
Read more - 04
Authorization on the tool call, not on the connection
The MCP mode parses JSON-RPC messages, so the method, the tool name and the tool arguments are each available to a Policy. Discovery can be open while individual tools are restricted, and an argument can be bounded rather than a tool allowed outright.
Read more - 05
Authorization on the inference request
The LLM mode normalizes the operation, requested model, streaming flag, declared tools, input modalities and declared output-token maximum, so which model an agent may use and under what conditions is a policy decision rather than which key it was given.
Read more - 06
Bounds that hold regardless of the prompt
Request body size, streamed event size, estimated input tokens, declared output tokens and declared tool count are enforced by the gateway before a request leaves the Cluster, independently of what the agent was asked to do.
Read more - 07
Somewhere isolated to run
Cordium, built on Octelium, provides reproducible sandboxes for agents and developers on the same Kubernetes infrastructure. Processes inside a Workspace reach authorized Services through the Workspace identity, with no secrets placed inside the sandbox.
Read more - 08
A record of what it actually did
Every request produces an identity-aware AccessLog naming the User and Session alongside the tool called, the arguments, the model used and the tokens consumed, streamed in real time over OpenTelemetry to your own log management and SIEM providers.
Read more
Most of this is not specific to AI. It is ordinary identity and access management, applied to identities that are created faster, act more often and are harder to interview afterwards.
The same platform capabilities ship with every deployment, whichever way you use it.
Frequently asked
- How does an AI agent authenticate?
- As a workload User, using the same identity model as a human User. It can present an authentication token, use the standard OAuth2 client credentials flow against the Cluster's token endpoint, use an access token directly as a bearer token, or authenticate secretlessly with a federated OpenID Connect assertion issued by the platform running it, such as GitHub Actions, a cloud provider or a Kubernetes cluster. No proprietary SDK is required.
- Can individual tool calls be authorized?
- Yes. The MCP mode understands JSON-RPC messages, so the method and the tool, prompt or resource name are separate normalized fields, and the parsed request body is available for arguments that have no normalized field. That lets tools/list stay open for discovery while tools/call is restricted per tool, per group and per argument value.
- What stops an agent from leaking a credential?
- It never receives one. Upstream credentials are stored in the Cluster as Secrets and injected into the upstream connection after a request has been authorized, and downstream Authorization, X-Api-Key and Api-Key credentials are stripped before proxying. The agent authenticates as itself and reaches the resource through the proxy, so there is no provider API key, database password or SSH key inside its environment to exfiltrate.
- Can different agents have different privileges on the same resource?
- Yes. Dynamic configuration selects the upstream, the upstream account and the credential per request from identity and request context, so a release agent and a research agent can share one Service URL while reaching different backends with different rights. Policies attach to a Service, a Namespace, a User, a Group or a Credential.
- Where do agents actually run?
- Wherever you run them. If you want the execution environment as well, Cordium is a free and open source sandbox platform built on Octelium and on the same Kubernetes infrastructure. Workspaces are built from OCI images, Dockerfiles, git repositories or devcontainers, run rootless, and reach authorized Services through the Workspace identity with no secrets inside the sandbox.
- Are prompts and tool arguments recorded?
- It depends on the mode and is configurable per Service. MCP request and response bodies are captured by default, because inspecting JSON-RPC messages is usually the point of the audit, and can be disabled. LLM request and response bodies are not captured by default, because prompts and outputs commonly contain sensitive data, and can be enabled where the audit backend and its retention policy are appropriate for them.
Related solutions
MCP gateway
An identity-aware Model Context Protocol gateway that authorizes JSON-RPC methods and individual tool calls.
Read moreAI gateway
An identity-aware gateway for OpenAI and Anthropic APIs, with per-request control over models, tools and token limits.
Read moreZero Trust Network Access
Octelium as a complete ZTNA and BeyondCorp platform for humans, workloads and AI agents on a single architecture.
Read moreDeploy Octelium on your own infrastructure in minutes
Free and open source. Self-hosted. No vendor lock-in.