← Back to Plugins
Tools

Dcp Output Controller

hiatamaworkshop By hiatamaworkshop 👁 101 views ▲ 0 votes

DCP output controller plugin for OpenClaw — constrains agent output via controller schemas

GitHub

Install

npm install
npm

Configuration Example

# profiles/worker-bot.yaml
name: worker-bot
default_mode: report
allowed_modes: [report, log, brief]
controllers:
  report:
    visible_fields: [action, target, detail]  # cost hidden
escalation:
  trigger: "error_count > 3"
  unlock: dialogue

README

# DCP Output Controller

```
HEARTBEAT.md (input)             LLM                 Telegram (output)
────────────────────             ───                 ─────────────────
$S:["sched:v1",
    "interval","task",           Judges.             ["done","/v1/auth","200 ok",42]
    "target","mode"]             Executes.           ["error","/v1/orders","timeout",0]
["30m","health-check",      →   No prose.       →          ↓ decode
 "/v1/auth,/v1/orders",                             ✓ /v1/auth — 200 ok (42ms)
 "report"]                                          ✗ /v1/orders — timeout
```

**DCP in. DCP out. LLM as a judgment engine, not a prose generator.**

---

OpenClaw plugin that constrains agent output via DCP controller schemas. Instead of unrestricted natural language, agents output structured positional arrays that are decoded into human-readable text for messaging platforms.

## Why

- Output tokens cost ~4x input tokens — nobody optimizes output structure
- Claw-type agents (OpenClaw, etc.) spend most of their time on non-interactive tasks (heartbeat monitoring, scheduled jobs) where natural language responses are waste
- Structured output enables downstream aggregation, storage, and analysis without re-parsing
- See [examples/HEARTBEAT.md](examples/HEARTBEAT.md) for a full DCP-native heartbeat configuration

## Architecture

```
Mode Layer          dialogue | report | log | brief
                         ↓
Controller Layer    DcpSchemaDef — positional array schema per mode
                         ↓
Profile Layer       Agent access control — which controllers, which fields
```

**Shadow Layering** — compression gradient from most to least constrained:

```
brief  ──→  log  ──→  report  ──→  dialogue
no escape   msg free  detail free  full NL
```

## Quick Start

```bash
npm install
npm test          # 35 tests
npx tsx demo.ts   # live pipeline demo
```

## Pipeline

```
1. Profile resolves mode + allowed controllers
2. DcpSchema injected into system prompt (before_prompt_build hook)
3. LLM outputs DCP rows: ["done", "/v1/auth", "200 ok", 42]
4. Rows validated via DcpSchema.validateRow()
5. Decoded via DcpDecoder: "✓ /v1/auth — 200 ok (42ms)"
6. Delivered to messaging platform
```

## Output Modes

| Mode | DCP | Shadow Index | Use Case |
|------|-----|-------------|----------|
| `dialogue` | OFF | N/A | Interactive conversation |
| `report` | ON | `detail` field | Task completion summaries |
| `log` | ON | `msg` field | Continuous event stream |
| `brief` | ON | none | Minimal status only |

## Agent Profiles

```yaml
# profiles/worker-bot.yaml
name: worker-bot
default_mode: report
allowed_modes: [report, log, brief]
controllers:
  report:
    visible_fields: [action, target, detail]  # cost hidden
escalation:
  trigger: "error_count > 3"
  unlock: dialogue
```

Worker-bot **cannot** use dialogue mode — the profile structurally prevents free-form output.

## Controller Schemas

Schemas use `DcpSchemaDef` format from [dcp-wrap](../dcp-wrap):

```json
{
  "$dcp": "schema",
  "id": "ctrl-report:v1",
  "fields": ["action", "target", "detail", "cost"],
  "fieldCount": 4,
  "types": {
    "action": { "type": "string", "enum": ["done", "error", "skip", "partial"] },
    "target": { "type": "string" },
    "detail": { "type": ["string", "null"] },
    "cost": { "type": ["number", "null"] }
  },
  "templates": {
    "done": "✓ {{target}} — {{detail}} ({{cost}}ms)",
    "error": "✗ {{target}} — {{detail}}"
  }
}
```

## dcp-wrap Integration

This plugin depends on [dcp-wrap](../dcp-wrap) for core DCP primitives:

- `DcpSchema` — schema loading, `sHeader()`, `validateRow()`, `fieldBit()`, `fieldsFromMask()`
- `DcpDecoder` — template-based decode: schema + row → human-readable text
- `DcpSchemaDef` — schema format used by controller JSON files

No duplicate schema/decode/validate logic — everything flows through dcp-wrap.

## OpenClaw Integration

### As Plugin

```
openclaw.plugin.json → hooks:
  before_prompt_build  →  inject controller schema into system prompt
  assistant            →  intercept output, validate, decode
```

### As Skill

`SKILL.md` provides `/mode <mode>` command for mode switching.

## Project Structure

```
dcp-output-controller/
├── controllers/          DcpSchemaDef + templates
│   ├── report.json
│   ├── log.json
│   └── brief.json
├── profiles/             Agent access control (YAML)
├── src/
│   ├── decode.ts         Thin wrapper around DcpDecoder
│   ├── profiles.ts       Profile loader + access control
│   ├── inject.ts         System prompt schema injection
│   ├── intercept.ts      Output validation + decode
│   └── hooks/            OpenClaw-specific hook wrappers
├── tests/                35 tests
├── demo.ts               Full pipeline demo
└── DESIGN.md             Detailed architecture doc
```

## Docker Testing

```bash
docker compose up    # mock-llm + controller test harness
curl localhost:8080  # simulate agent interaction
```

No phone/messaging app needed — full pipeline testable with HTTP.

## What is DCP?

DCP (Dense Context Protocol) is a schema-driven encoding that replaces verbose JSON/NL with positional arrays for LLM context. Originally designed for **input compression** (system → LLM), this plugin introduces the **output direction** (LLM → human) — the first practical use case for DCP decode.

```
Traditional:  {"action":"done","target":"/v1/auth","detail":"200 ok","cost":42}
DCP:          ["done","/v1/auth","200 ok",42]
Human:        ✓ /v1/auth — 200 ok (42ms)
```

The schema carries field names, so decode is a lookup — not inference.

### Core DCP Primitives (from dcp-wrap)

| Primitive | Direction | Used By |
|-----------|-----------|---------|
| `DcpSchema` | both | Schema loading, `$S` header, validation, bitmask field selection |
| `DcpEncoder` | input (system→LLM) | Encode JSON objects into positional arrays |
| `DcpDecoder` | output (LLM→human) | Decode positional arrays into human-readable text via templates |
| `dcpEncode()` | input | One-step inline encode for known structures |

### Related Repositories

- **[dcp-wrap](https://github.com/hiatamaworkshop/dcp-wrap)** — Core DCP library: schema, encoder, decoder. This plugin's only runtime dependency.
- **[engram](https://github.com/hiatamaworkshop/engram)** — Memory system for AI agents. Uses DCP for context-efficient knowledge retrieval.

### Further Reading

- [DESIGN.md](DESIGN.md) — Detailed 3-layer architecture, shadow layering, access control matrix
- [OpenClaw Plugin Docs](https://docs.openclaw.ai/tools/plugin) — How plugins integrate with OpenClaw Gateway
- [OpenClaw Heartbeat](https://docs.openclaw.ai/gateway/heartbeat) — Background scheduler where DCP output saves the most tokens

## License

MIT
tools

Comments

Sign in to leave a comment

Loading comments...