MAQPNADocs

Agents, sessions, sandboxes and trust tiers#

Four nouns describe where an agent's code runs. They map to Kubernetes resources in the maqpna.com/v1alpha1 API group.

Term Kind Scope In one sentence
agent Agent Namespaced The definition: image, trust tier, tools, model, policy, scopes, budget
session AgentSession (short name asess) Namespaced One run of an agent for one user, with its own sandbox, identity and token
sandbox upstream Sandbox or SandboxClaim Namespaced The isolated environment one session runs in
trust tier TrustTier (short name tier) Cluster The isolation level: RuntimeClass, jurisdiction, egress mode, maximum TTL
flowchart LR
    TT["TrustTier tier-1-microvm<br/>runtimeClassName: kata-fc<br/>jurisdiction: EU-DE"]
    A["Agent team-a/coder<br/>image · tools · model<br/>policyRef · scopes"]
    S1["AgentSession fix-4821<br/>user alice@acme.eu"]
    S2["AgentSession fix-4822<br/>user bob@acme.eu"]
    SB1["Sandbox fix-4821<br/>(Kata microVM)"]
    SB2["Sandbox fix-4822<br/>(Kata microVM)"]
    A -- "spec.tier" --> TT
    S1 -- "spec.agentRef" --> A
    S2 -- "spec.agentRef" --> A
    S1 -- owns --> SB1
    S2 -- owns --> SB2

Agent#

An agent is an AI program that uses tools. MAQPNA does not care how it is written; it needs an Agent resource that says:

  • image (and optionally command, args, env): what to run;
  • tier: the name of a TrustTier;
  • tools[]: the MCP servers it may call, each by serverRef to an MCPServer (or the deprecated upstreamURL);
  • model: an OpenAI-compatible endpoint, reached only through the gateway's model route;
  • policyRef: the ToolPolicy in its namespace;
  • scopes: what its sessions may request (default tools:<name> for each tool);
  • budget, maxConcurrentSessions, idleTimeout (default 15 minutes), maxSessionTTL;
  • profile: default, browser or codeInterpreter, which adds sidecars to the sandbox.

The agent is only a definition. Nothing runs until a session is created.

Session#

A session is one run of an agent, from start to result, acting for one person (spec.user). Every governed call belongs to exactly one session. A session has:

  • its own sandbox, owned by the AgentSession and deleted with it;
  • its own identity: a SPIFFE-style ID spiffe://<trust-domain>/ns/<ns>/agent/<agent>/session/<session>;
  • its own token, minted by the identity broker with the session's scopes, which must be a subset of the agent's (ScopeEscalation otherwise);
  • a TTL: min(spec.ttl or the 1-hour default, tier maxSessionTTL, agent maxSessionTTL).

A session moves through these phases (status.phase):

stateDiagram-v2
    [*] --> Pending
    Pending --> Provisioning: admitted (quota free)
    Pending --> Failed: AgentNotFound, TierNotFound,<br/>ScopeEscalation, SovereigntyViolation
    Provisioning --> Running: sandbox Ready<br/>(claim mode: pod bootstrapped)
    Provisioning --> Failed: AttestationFailed, InputInvalid,<br/>PrincipalUnverified, Revoked
    Running --> Suspended: spec.suspend, idle timeout,<br/>revocation with action suspend
    Suspended --> Running: resume or new activity
    Running --> Completed: sandbox Finished or TTL reached
    Suspended --> Completed: TTL reached
    Running --> Failed: revocation with action terminate
    Completed --> [*]
    Failed --> [*]

When a session ends, the operator records a result in status.outcome.result: Succeeded, Failed, Expired, Revoked or Cancelled. Phase and result are separate: an agent that exits with code 1 ends in phase Completed with result Failed. The full reconcile is in session lifecycle.

Sandbox#

The sandbox is the isolated environment one session runs in. MAQPNA does not build its own: it creates an upstream Sandbox (or, for warm pools, a SandboxClaim) from the kubernetes-sigs/agent-sandbox project, unstructured so MAQPNA is not tied to one agent-sandbox release (--sandbox-api-version, default v1beta1).

Every sandbox pod the operator builds is hardened the same way:

  • runtimeClassName from the trust tier, so agent code never runs under plain runc;
  • non-root (UID and GID 65532), seccomp RuntimeDefault, read-only root filesystem, all capabilities dropped;
  • automountServiceAccountToken: false and enableServiceLinks: false: the agent gets no Kubernetes credentials;
  • the session token mounted read-only at /var/run/maqpna/token;
  • a per-session NetworkPolicy <session>-maqpna: ingress only from the gateway, egress only to DNS and the gateway (plus the attestation service or identity broker bootstrap port when needed).

The sandbox never learns real tool or model URLs. It gets MAQPNA_TOOL_<NAME>_URL={gateway}/mcp/<name> and MAQPNA_MODEL_ENDPOINT={gateway}/llm/<route>/v1.

Warm pools#

A trust tier with sandboxTemplateName and warmPoolSize keeps pre-started sandboxes in an upstream SandboxWarmPool named maqpna-<tier>. Sessions on that tier claim one. Because agent-sandbox only adopts warm pods for claims without environment variables, MAQPNA uses late binding: the claim carries nothing, and the adopted pod fetches its environment, task and a fresh token from the identity broker's /v1/bootstrap endpoint with a projected ServiceAccount token. No session token is ever stored in the claim, the pod spec or the session status.

Trust tier#

The trust tier is the isolation level a session runs at. The Helm chart ships three:

Tier Isolation RuntimeClass What it protects against
tier-0 (gVisor) gvisor gvisor (runsc) Most kernel attack surface: system calls are served by a user-space kernel
tier-1 (microVM) microvm kata-fc (Kata Containers + Firecracker) Host kernel exploits: each sandbox has its own guest kernel
tier-2 (confidential VM) confidential kata-qemu-snp (Kata with AMD SEV-SNP or Intel TDX) The infrastructure operator reading memory: memory is encrypted and the token is released only after attestation

A TrustTier also sets jurisdiction and allowedNodeLabels (required node affinity), egress (gateway-only or deny-all), defaultResources, maxSessionTTL and attestationRequired. The isolation field is descriptive: the operator copies runtimeClassName into the pod, and uses isolation only for attestation and sovereignty checks.

What you see#

maqpna session list prints one row per session:

NAME      AGENT  USER           PHASE      OUTCOME    READY-IN  AGE
fix-4790  coder  bob@acme.eu    Completed  Succeeded  2.43s     118m
fix-4821  coder  alice@acme.eu  Running    -          1.71s     3m

The columns are fixed in cmd/maqpna/session.go; the rows are illustrative. Rows are sorted by namespace and name, and empty values print as -. READY-IN is status.readyIn, the time from creation to first Running. See maqpna session list, maqpna session describe and maqpna tier list.