On some adapters, including Codex CLI, a deny catch-all is enforced as a prompt rather than a hard block. This spec uses claude-code for that reason. Confirm the behavior of your chosen adapter before treating default: deny as a boundary.
Review Documents Against a Policypublic
Last verified 22 Sep 2026
DigitalOcean Harness Runtime combines the functionality of a lightweight microVM, built-in tools like chromium and a coding sandbox needed by agents to do work. The product offers rich lifecycle APIs that persist conversational history and working state across sessions, with pause/resume/fork semantics so that developers can control costs and adapt workflows to the nonlinear quirks of agentic work. See What You Can Build for example use cases.
Contract review, vendor questionnaires, and policy checks are pattern matching against a checklist, and an agent is good at a first pass. What makes this different from the earlier examples is not the work, it is the constraints: the material is sensitive, so the environment should be able to do almost nothing except read it and write a summary.
This example is the locked-down pattern. It produces a reviewer’s first pass, flagging clauses for a human to decide on. It does not decide anything, and it is not a substitute for advice from a qualified professional.
Environment Spec
Save the following as document-review.yaml:
name: contract-review
agent: claude-code
size: mars-2vcpu-4gb
persistent_workspace: false
idle_timeout: 15m
repos:
- your-org/contracts
env:
HARNESS_INFERENCE_MODEL: anthropic-claude-5-sonnet
secrets:
HARNESS_INFERENCE_API_KEY: ${HARNESS_INFERENCE_API_KEY}
GITHUB_TOKEN: ${GITHUB_TOKEN}
egress:
- github.com
- api.github.com
skills:
- name: clause-checklist
description: "Use when reviewing any inbound contract, order form, or vendor agreement."
instructions: |
# Clause Checklist
For each document, report on every item below. Say "not present"
explicitly rather than staying silent, because a missing clause is
usually the finding.
- Governing law and venue
- Limitation of liability, and whether it is mutual
- Indemnity scope
- Auto-renewal and the notice window to prevent it
- Data processing terms and subprocessor consent
- Assignment on change of control
Quote the clause text you are describing. Flag anything that departs
from our standard position; do not decide whether to accept it.
permissions:
default: deny
filesystem:
mode: workspace-write
rules:
- tool: file.read
action: allow
- tool: file.write
action: allow
- tool: bash
action: allowThree things are doing the security work here, and each is worth keeping if you adapt this.
default: deny inverts the usual posture. Anything not named in a rule is blocked, so attaching a tool to the environment later does not silently grant the agent the ability to use it.
bash is allowed, and that is the honest cost of cloning. There is no separate clone permission; the agent clones by running git in a shell. Allowing bash also means there is no push control left to apply: no adapter currently implements a git.push permission target, so a shell is a shell. Plan for the agent being able to reach anything the network policy permits.
egress lists only GitHub. The platform adds the hosts the session cannot run without, including the DigitalOcean inference endpoint, and nothing else is reachable. The documents arrive from a private repository, so a prompt injection that tells the agent to post the text somewhere has nowhere to post it. Treat this as shrinking the blast radius rather than as an airtight boundary: an agent with bash and a route to GitHub can still write to GitHub.
persistent_workspace: false means the checkout does not survive. Combined with removing the session when the review is done, the documents do not sit in a warm sandbox between runs.
Run It
export HARNESS_INFERENCE_API_KEY=<your-model-access-key>
export GITHUB_TOKEN=<your-github-token>
doctl harness-runtime launch --spec document-review.yaml \
--prompt "Clone your-org/contracts and review every file under inbound/2026-q3/. Produce one summary per document at review/<filename>.md."Read the summaries in the session, then tear the environment down:
doctl harness-runtime remove contract-reviewFor what DigitalOcean retains from a session and for how long, see Managed Agents Data Privacy. The document text also reaches the model, so check the retention terms of the model you name in HARNESS_INFERENCE_MODEL before you review anything sensitive. A few third-party models on Serverless Inference carry mandatory retention, which is listed per model in Available Models and explained in Inference Data Privacy.
Adapt It
| To do this | Change this |
|---|---|
| Review a different document class | Rewrite the checklist in instructions. The checklist is the whole product here; the spec around it rarely changes. |
| Pull documents from somewhere other than GitHub | Attach an MCP server under tools, add its host to egress, and add a rule allowing that specific server. Inline MCP hosts are not added to the allowlist automatically. |
| Remove the network path entirely | Drop repos, deny bash, and paste the document text into the prompt. With no shell and no tools, the agent has no way to open a connection whatever the egress policy permits. |
| Run it on every new document | Wrap it in a webhook trigger, with the unattended permissions rules from Review Pull Requests. |
| Keep a reviewer in the loop per finding | Change the writes to action: ask for an interactive session. ask is rejected on triggered runs. |
Related
- Permission Policies for how a deny default interacts with rule order and adapter support.
- Network Egress for what an allowlist does and does not cover.
- Secrets and Configuration for keeping credentials out of the guest environment.