← Back to Plugins
Tools

Dcp Output Controller

hiatamaworkshop By hiatamaworkshop 👁 7 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...