PUNKthe adaptive runtime

//DOCS Governance Examples

Example policies and expected outcomes for common governed agent actions.

Governance Examples

These examples use the policy fields Punk accepts today:

  • name, version, optional description
  • appliesTo.trustTiers, appliesTo.agentIds, or appliesTo.tags
  • ordered rules with effect, actions, and optional requiresApproval
  • defaultEffect

Policies live in PUNK_POLICIES_DIR. Rules match actions shaped as <verb>:<resource> such as model:chat, read:crm, write:crm, write:web, and destroy:*.

Observe vs Optimize

Punk API keys have observe or optimize mode. There is no separate policy YAML field for enforcement mode.

Key modeRuntime behavior
observeLive provider serves the user. Policy denials and approvals are audited with enforcement: "skipped (observe mode)", route explanations can show a ghost blocked route, and optimized/cache routes are recorded as ghost savings instead of being served. Request-time approval verdicts do not create operator approval rows.
optimizePolicy is enforced. deny and approval_required fail closed, approval work items can be created, and proven caches/artifacts may serve traffic.

For stateful web actions, observe-mode reads can run, but web writes are refused because form submits and submit-button clicks are real remote writes.

Tool Actions and Side Effects

SDK and model-declared tools should declare sideEffectLevel:

LevelRuntime meaningPolicy action shape for SDK-style tool names
0Pure/local computationread:<tool-namespace> when governed as a read
1External readread:<tool-namespace>
2Reversible/idempotent writewrite:<tool-namespace>
3User-visible writewrite:<tool-namespace>
4High-impact writedestroy:<tool-namespace>

For SDK-style names, Punk uses the prefix before the last dot as the namespace. For example, crm.lookup at level 1 maps to read:crm, while crm.updateAccount at level 3 maps to write:crm. Undeclared or unknown tools default to level 3, so they are treated conservatively.

Managed connectors publish their own domain policy actions in docs/CONNECTORS.md such as read:ticket, write:ticket, write:crm, and write:payment. Use those connector action names when governing managed connector tools.

Read-Only Support Agent

Use this when a support assistant may classify, summarize, and retrieve context, but must not change tickets, accounts, files, or execute commands.

name: support-readonly
version: "1.0"
description: Support agent can chat and read context, but cannot write.

appliesTo:
  tags: [support-readonly]

rules:
  - effect: allow
    actions: ["model:chat", "read:*"]

  - effect: deny
    actions: ["write:*", "destroy:*", "execute:*"]

defaultEffect: deny

Expected outcomes:

Runtime eventOptimize outcome
Chat completion, model:chatAllowed. The response may route live, exact-cache, semantic-cache, artifact, or model-substitution depending on available evidence.
Support read, for example read:ticket or SDK tool zendesk.get_ticket declared level 1Allowed and auditable. Read-only tool results can be eligible for tool caching when configured with a TTL.
Ticket comment, for example write:ticket or SDK tool zendesk.comment_ticket declared level 3Blocked with a policy deny; the tool/write should not execute.
Shell or command tool, execute:*Blocked with a policy deny.

In observe mode, the model request still completes live. The blocked write policy verdict is recorded for review instead of being enforced at the request-routing layer.

Approval-Required CRM Write

Use this when CRM reads are safe, but account changes need a human exception before execution.

name: crm-write-approval
version: "1.0"
description: CRM writes need operator approval.

appliesTo:
  trustTiers: [verified, trusted]

rules:
  - effect: allow
    actions: ["model:chat", "read:*"]

  - effect: allow
    actions: ["write:crm"]
    requiresApproval: true

  - effect: deny
    actions: ["destroy:*", "execute:*"]

defaultEffect: deny

Expected outcomes:

Runtime eventOptimize outcome
read:crm or SDK tool crm.lookup declared level 1Allowed.
write:crm from a managed connector or SDK tool crm.updateAccount declared level 2 or 3Fails closed as approval_required. Gateway requests return a 403 punk_approval_required response and the run route is blocked.
Pending approvalPunk creates or reuses a policy_exception approval tied to the tenant, app, agent, action, and run.
Approved exceptionMatching future requests for the same agent/action are allowed until the exception expires. Hard deny rules are not softened by exception approval.

In observe mode, the same approval verdict is recorded as a ghost blocked/held route, but the live model response is returned and no approval work item is created.

Blocked Private Web Fetch

This example allows public web context reads while blocking web writes. Private-network blocking is not a YAML policy field; it is the always-on URL guard used by SOM fetches, web sessions, workflow web fetches, and redirects.

name: public-web-context
version: "1.0"
description: Allow public web reads, block web writes.

appliesTo:
  trustTiers: [unverified, verified, trusted, privileged]

rules:
  - effect: allow
    actions: ["model:chat", "read:web"]

  - effect: deny
    actions: ["write:web"]

defaultEffect: deny

Expected outcomes:

Runtime eventOutcome
POST /api/v1/web/fetch with https://example.com/pricingAllowed when the URL is valid and publicly routable. The response includes SOM/context and may use the SOM cache.
POST /api/v1/web/fetch with http://169.254.169.254/latest/meta-data, http://127.0.0.1:4100, http://10.0.0.1, .local, or .internalReturns 403 with category: "url_guard". Punk audits action web.fetch with decision deny; the upstream request is not made.
Public page redirects to a private/link-local URLReturns 403 with category: "url_guard" after the redirect target is checked.
Stateful web link click that navigates to a private destinationReturns 403 and audits web:action.blocked with governed action read:web.
Stateful form submit or submit-button clickGoverned as write:web at level 3. In optimize mode, the snippet above blocks it. In observe mode, web writes are refused instead of ghost-allowed.

Open dev mode is the exception for local demos: when there is no bootstrap API key, no login requirement, no authenticated caller, and no users, private/loopback fetches can be allowed. Authenticated deployments can only opt into private fetches with PUNK_ALLOW_PRIVATE_WEB_FETCH=true.

Level 3 and Level 4 Side-Effect Policy

Use this when user-visible writes should pause for approval and high-impact or destructive actions should be blocked outright.

name: side-effect-boundary
version: "1.0"
description: Human approval for level-3 writes; hard block level-4 destroy actions.

appliesTo:
  trustTiers: [unverified, verified, trusted]

rules:
  - effect: allow
    actions: ["model:chat", "read:*"]

  - effect: allow
    actions: ["write:*"]
    requiresApproval: true

  - effect: deny
    actions: ["destroy:*", "execute:*"]

defaultEffect: deny

Expected outcomes:

Runtime eventOptimize outcome
SDK tool email.send declared level 3Maps to write:email, matches requiresApproval, and fails closed as approval_required.
SDK tool crm.lookup with no side-effect declarationDefaults to level 3, maps to write:crm, and is held for approval. Declare read-only tools as level 1 when they are truly read-only.
SDK tool billing.cancelSubscription declared level 4Maps to destroy:billing, matches destroy:*, and is denied.
Managed connector level-4 billing/payment toolGovern its published action such as write:payment; level-4 connector tools require approval by default and are suppressed in replay/shadow.
Replay or shadow evaluation with a level 2, 3, or 4 side effectThe side effect is recorded as planned/suppressed and is not executed.

The side-effect gate is conservative even without a matching YAML approval rule: level 4 live actions require approval unless the agent is privileged, and level 3 live actions require approval for unverified agents.

Observe-Mode Skipped Enforcement

This fixture-style policy denies chat for unverified agents. It is useful for proving observe mode before moving a tenant to optimize mode.

name: deny-unverified-chat
version: "1.0"
description: Block chat for unverified agents.

appliesTo:
  trustTiers: [unverified]

rules:
  - effect: deny
    actions: ["model:chat"]

defaultEffect: allow

Expected outcomes:

Key modeRuntime outcome
optimizeThe chat request returns 403 with type: "punk_policy_blocked" and code: "policy_blocked". The run has route blocked; route explanation policy decision is deny; audit records the deny.
observeThe chat request returns 200 from the live provider with x-punk-route: live. The run completes, route explanation keeps policy decision deny, and routeExplanation.ghost.route is blocked. Audit and policy.checked trace payloads include enforcement: "skipped (observe mode)".

Observe mode also skips serving optimized routes: cache and artifact hits are recorded as ghost savings rather than used for the user response.