---
title: Review Documents Against a Policy (public)
description: Run a locked-down Harness Runtime environment that reads contracts or policy documents, flags clauses against your checklist, and leaves nothing …
product: Managed Agents
url: https://docs.digitalocean.com/products/managed-agents/agent-harness-runtime/examples/review-documents/
last_updated: "2026-09-25"
---

> **For AI agents:** The documentation index is at [https://docs.digitalocean.com/llms.txt](https://docs.digitalocean.com/llms.txt). Markdown versions of pages use the same URL with `index.html.md` in place of the HTML page (for example, append `index.html.md` to the directory path instead of opening the HTML document).

# Review Documents Against a Policy (public)

DigitalOcean Harness Runtime provides managed, hardware-isolated microVM sandboxes with built-in tools such as Chromium to run harnesses and execute arbitrary code. Rich lifecycle APIs preserve conversational history and working state across sessions, letting you pause, resume, and fork work to control costs and adapt to the nonlinear nature of agentic workflows. Scale complete agents such as Claude Code or use sandboxes independently for code execution, all through the same service. See [What You Can Build](https://docs.digitalocean.com/products/managed-agents/agent-harness-runtime/details/what-you-can-build/index.html.md) 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`:

```yaml
name: contract-review
agent: claude-code
size: mars-2vcpu-4gb
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: allow
```

Three 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.

**Warning**:

  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.

## Run It

```shell
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:

```shell
doctl harness-runtime remove contract-review
```

For what DigitalOcean retains from a session and for how long, see [Managed Agents Data Privacy](https://docs.digitalocean.com/products/managed-agents/agent-harness-runtime/details/data-privacy/index.html.md). 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](https://docs.digitalocean.com/products/inference/details/models/index.html.md#foundation-models) and explained in [Inference Data Privacy](https://docs.digitalocean.com/products/inference/details/data-privacy/index.html.md#third-party-models).

## 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](https://docs.digitalocean.com/products/managed-agents/agent-harness-runtime/examples/review-pull-requests/index.html.md). |
| 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](https://docs.digitalocean.com/products/managed-agents/agent-harness-runtime/concepts/permissions/index.html.md) for how a deny default interacts with rule order and adapter support.
- [Network Egress](https://docs.digitalocean.com/products/managed-agents/agent-harness-runtime/concepts/egress/index.html.md) for what an allowlist does and does not cover.
- [Secrets and Configuration](https://docs.digitalocean.com/products/managed-agents/agent-harness-runtime/concepts/secrets/index.html.md) for keeping credentials out of the guest environment.