← Back to Skills
Automation

arbiter

5hanth By 5hanth 👁 15 views ▲ 0 votes

Push decisions to Arbiter Zebu for async human review.

GitHub
---
name: arbiter
description: Push decisions to Arbiter Zebu for async human review. Use when you need human input on plans, architectural choices, or approval before proceeding.
metadata: {"openclaw":{"requires":{"bins":["arbiter-push"]}}}
---

# Arbiter Skill

Push decisions to Arbiter Zebu for async human review. Use when you need human input on plans, architectural choices, or approval before proceeding.

## Installation

**Quick install via ClawHub:**
```bash
clawhub install arbiter
```

**Or via bun (makes CLI commands available globally):**
```bash
bun add -g arbiter-skill
```

**Or manual:**
```bash
git clone https://github.com/5hanth/arbiter-skill.git
cd arbiter-skill && npm install && npm run build
ln -s $(pwd) ~/.clawdbot/skills/arbiter
```

### Prerequisites

- [Arbiter Zebu](https://github.com/5hanth/arbiter-zebu) bot running (or just `bunx arbiter-zebu`)
- `~/.arbiter/queue/` directory (created automatically by the bot)

## Environment Variables

Set these in your agent's environment for automatic agent/session detection:

| Variable | Description | Example |
|----------|-------------|---------|
| `CLAWDBOT_AGENT` | Agent ID | `ceo`, `swe1` |
| `CLAWDBOT_SESSION` | Session key | `agent:ceo:main` |

## When to Use

- Plan review before implementation
- Architectural decisions with tradeoffs
- Anything blocking that needs human judgment
- Multiple related decisions as a batch

**Do NOT use for:**
- Simple yes/no that doesn't need explanation
- Urgent real-time decisions (use direct message instead)
- Technical questions you can research yourself

## Tools

### arbiter_push

Create a decision plan for human review.

**CLI:** `arbiter-push '<json>'` — takes a single JSON argument containing all fields.

```bash
arbiter-push '{
  "title": "API Design Decisions",
  "tag": "nft-marketplace",
  "context": "SWE2 needs these decided before API work",
  "priority": "normal",
  "notify": "agent:swe2:main",
  "decisions": [
    {
      "id": "auth-strategy",
      "title": "Auth Strategy", 
      "context": "How to authenticate admin users",
      "options": [
        {"key": "jwt", "label": "JWT tokens", "note": "Stateless"},
        {"key": "session", "label": "Sessions", "note": "More control"},
        {"key": "oauth", "label": "OAuth", "note": "External provider"}
      ]
    },
    {
      "id": "database",
      "title": "Database Choice",
      "context": "Primary datastore",
      "options": [
        {"key": "postgresql", "label": "PostgreSQL + JSONB"},
        {"key": "mongodb", "label": "MongoDB"}
      ],
      "allowCustom": true
    }
  ]
}'
```

**JSON Fields:**

| Field | Required | Description |
|-------|----------|-------------|
| `title` | Yes | Plan title |
| `tag` | No | Tag for filtering (e.g., project name) |
| `context` | No | Background for reviewer |
| `priority` | No | `low`, `normal`, `high`, `urgent` (default: normal) |
| `notify` | No | Session to notify when complete |
| `agent` | No | Agent ID (auto-detected from `CLAWDBOT_AGENT` env) |
| `session` | No | Session key (auto-detected from `CLAWDBOT_SESSION` env) |
| `decisions` | Yes | Array of decisions |

**Decision object:**

| Field | Required | Description |
|-------|----------|-------------|
| `id` | Yes | Unique ID within plan |
| `title` | Yes | Decision title |
| `context` | No | Explanation for reviewer |
| `options` | Yes | Array of `{key, label, note?}` |
| `allowCustom` | No | Allow free-text answer (default: false) |
| `default` | No | Suggested option key |

**Returns:**

```json
{
  "planId": "abc123",
  "file": "~/.arbiter/queue/pending/ceo-api-design-abc123.md",
  "total": 2,
  "status": "pending"
}
```

### arbiter_status

Check the status of a decision plan.

**CLI:** `arbiter-status <plan-id>` or `arbiter-status --tag <tag>`

```bash
arbiter-status abc12345
# or
arbiter-status --tag nft-marketplace
```

**Returns:**

```json
{
  "planId": "abc123",
  "title": "API Design Decisions",
  "status": "in_progress",
  "total": 3,
  "answered": 1,
  "remaining": 2,
  "decisions": {
    "auth-strategy": {"status": "answered", "answer": "jwt"},
    "database": {"status": "pending", "answer": null},
    "caching": {"status": "pending", "answer": null}
  }
}
```

### arbiter_get

Get answers from a completed plan.

**CLI:** `arbiter-get <plan-id>` or `arbiter-get --tag <tag>`

```bash
arbiter-get abc12345
# or
arbiter-get --tag nft-marketplace
```

**Returns:**

```json
{
  "planId": "abc123",
  "status": "completed",
  "completedAt": "2026-01-30T01:45:00Z",
  "answers": {
    "auth-strategy": "jwt",
    "database": "postgresql",
    "caching": "redis"
  }
}
```

**Error if not complete:**

```json
{
  "error": "Plan not complete",
  "status": "in_progress",
  "remaining": 2
}
```

### arbiter_await

Block until plan is complete (with timeout).

```bash
arbiter-await abc12345 --timeout 3600
```

Polls every 30 seconds until complete or timeout.

**Returns:** Same as `arbiter_get` on completion.

## Usage Examples

### Example 1: Plan Review

```bash
# Push plan decisions (single JSON argument)
RESULT=$(arbiter-push '{"title":"Clean IT i18n Plan","tag":"clean-it","priority":"high","notify":"agent:swe3:main","decisions":[{"id":"library","title":"i18n Library","options":[{"key":"i18next","label":"i18next"},{"key":"formatjs","label":"FormatJS"}]},{"id":"keys","title":"Key Structure","options":[{"key":"flat","label":"Flat (login.button)"},{"key":"nested","label":"Nested ({login:{button}})"}]}]}')

PLAN_ID=$(echo $RESULT | jq -r '.planId')
echo "Pushed plan $PLAN_ID — waiting for human review"
```

### Example 2: Check and Proceed

```bash
# Check if decisions are ready
STATUS=$(arbiter-status --tag nft-marketplace)

if [ "$(echo $STATUS | jq -r '.status')" == "completed" ]; then
  ANSWERS=$(arbiter-get --tag nft-marketplace)
  AUTH=$(echo $ANSWERS | jq -r '.answers["auth-strategy"]')
  echo "Using auth strategy: $AUTH"
  # Proceed with implementation
else
  echo "Still waiting for $(echo $STATUS | jq -r '.remaining') decisions"
fi
```

### Example 3: Blocking Wait

```bash
# Wait up to 1 hour for decisions
ANSWERS=$(arbiter-await abc12345 --timeout 3600)

if [ $? -eq 0 ]; then
  # Got answers, proceed
  echo "Decisions ready: $ANSWERS"
else
  echo "Timeout waiting for decisions"
fi
```

## Best Practices

1. **Batch related decisions** — Don't push one at a time
2. **Provide context** — Human needs to understand tradeoffs
3. **Use tags** — Makes filtering easy (`--tag project-name`)
4. **Set notify** — So blocked agents get woken up
5. **Use priority sparingly** — Reserve `urgent` for true blockers

## File Locations

| Path | Purpose |
|------|---------|
| `~/.arbiter/queue/pending/` | Plans awaiting review |
| `~/.arbiter/queue/completed/` | Answered plans (archive) |
| `~/.arbiter/queue/notify/` | Agent notifications |

## Checking Notifications (Agent Heartbeat)

In your HEARTBEAT.md, add:

```markdown
## Check Arbiter Notifications

1. Check if `~/.arbiter/queue/notify/` has files for my session
2. If yes, read answers and proceed with blocked work
3. Delete notification file after processing
```

## Troubleshooting

| Issue | Solution |
|-------|----------|
| Plan not showing in Arbiter | Check file is valid YAML frontmatter |
| Answers not appearing | Check `arbiter_status`, may be incomplete |
| Notification not received | Ensure `--notify` was set correctly |

## See Also

- [Arbiter Zebu Architecture](https://github.com/5hanth/arbiter-zebu/blob/main/ARCHITECTURE.md)
- [Arbiter Zebu Bot](https://github.com/5hanth/arbiter-zebu)
automation

Comments

Sign in to leave a comment

Loading comments...