---
title: Agents
description: A reviewer, a translator and a weekly auditor that work on your content next to your Hollware, and never publish.
section: guides
order: 6
---

# Agents

`@hollware/agents` runs three agents on a Worker of your own, next to your Hollware:

| Agent      | What it does                                                                                                   |
| ---------- | -------------------------------------------------------------------------------------------------------------- |
| Reviewer   | Comments once on each pending review: clarity, the voice of your style guide, claims without an example.       |
| Translator | Drafts the missing translation of a published entry, fixes what the contracts refuse, and asks for its review. |
| Auditor    | Once a week, reports much-read entries that have not changed in months, and published entries the contracts refuse now. |

None of them publishes. Their MCP client refuses every tool that publishes or decides (`publish`, `approve_review`, `request_changes`, `unpublish`), whatever their token holds. A translation reaches readers only when a person approves its review; an audit is a draft.

## Set them up

1. Create a token for them, with no publishing:

```sh
npx hollware token create --label agents --scopes content:read,content:write --remote
```

2. Create a KV namespace for what they remember:

```sh
npx wrangler kv namespace create my-cms-agents
```

3. Make a Worker for them. Its `wrangler.jsonc`, with the name of your Hollware Worker in `service`:

```jsonc
{
  "name": "my-cms-agents",
  "main": "src/index.ts",
  "compatibility_date": "2026-10-06",
  "vars": { "HOLLWARE_PUBLIC_URL": "https://cms.example.com" },
  "services": [{ "binding": "HOLLWARE", "service": "my-cms" }],
  "ai": { "binding": "AI" },
  "kv_namespaces": [{ "binding": "AGENTS_KV", "id": "<the id of step 2>" }]
}
```

And `src/index.ts`:

```ts
import { createHollwareAgents } from '@hollware/agents'
import { WorkerEntrypoint } from 'cloudflare:workers'

const agents = createHollwareAgents({
  auditor: { collection: 'reports', locale: 'en' },
})

export class HollwareAgents extends WorkerEntrypoint<Env> {
  async run() {
    await agents.run(this.env)
  }
}

export default { fetch: agents.fetch, scheduled: agents.scheduled }
```

4. Give it the token, and deploy:

```sh
npx wrangler secret put HOLLWARE_AGENT_TOKEN
npx wrangler deploy
```

5. Let your Hollware wake them. In the `wrangler.jsonc` of your Hollware, then deploy it again:

```jsonc
"services": [{ "binding": "AGENTS", "service": "my-cms-agents", "entrypoint": "HollwareAgents" }]
```

Hollware's cron trigger wakes the agents every ten minutes, so they need no cron trigger of their own: the Workers free plan has five for the account. Each run is one agent, in turn: the reviewer, then the translator, then the auditor, which checks a dozen entries a run and writes its report once a week. One agent at a time keeps a run within the fifty calls a free Worker may make.

If you have cron triggers to spare, give the agents one instead of the binding: `scheduled` runs them the same way.

## The model

The agents use Workers AI, `@cf/meta/llama-3.3-70b-instruct-fp8-fast` unless you name another. They stop for the day after 100 calls to the model, which keeps them in the free allowance of Workers AI:

```ts
createHollwareAgents({ model: '@cf/openai/gpt-oss-120b', dailyLimit: 50, gateway: 'my-gateway' })
```

`gateway` sends the calls through an AI Gateway, for its logs and its cache. For another provider, pass a function that takes the messages and returns the answer.

## The report

The auditor needs no model. Its report gathers what its runs found in the last week, with the much-read pages that have not changed in six months. It writes the report as a draft of the collection you give it, with the slug `audit-<day>`, and never publishes it. The collection needs a `title` and a `description` in its schema, or a `frontmatter` function that returns what it does need.

To get the report in Slack as well, set the URL of an incoming webhook as a secret:

```sh
npx wrangler secret put AGENTS_WEBHOOK_URL
```

The auditor reports much-read pages only when the site's analytics are connected: see [Search and analytics](/docs/search-and-analytics/).

::callout{type="tip"}
Turn an agent off with `reviewer: false`, `translator: false` or `auditor: false`.
::
