merge-engine 0.1.0

A non-LLM merge conflict resolver using structured merge, Version Space Algebra, and search-based techniques
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
# Agents


TinyClaw supports running multiple AI agents simultaneously, each with its own isolated workspace, configuration, and conversation state. This allows you to have specialized agents for different tasks while maintaining complete isolation.

## Overview


The agent management feature enables you to:

- **Run multiple agents** with different models, providers, and configurations
- **Route messages** to specific agents using `@agent_id` syntax
- **Isolate conversations** - each agent has its own workspace directory and conversation history
- **Specialize agents** - give each agent a custom system prompt and configuration
- **Switch providers** - mix Anthropic (Claude) and OpenAI (Codex) agents
- **Customize workspaces** - organize agents in your own workspace directory

## Architecture


```
┌─────────────────────────────────────────────────────────────┐
│                    Message Channels                          │
│              (Discord, Telegram, WhatsApp)                   │
└────────────────────┬────────────────────────────────────────┘
                     │ User sends: "@coder fix the bug"
┌─────────────────────────────────────────────────────────────┐
│                   Queue Processor                            │
│  • Parses @agent_id routing prefix                          │
│  • Falls back to default agent if no prefix                 │
│  • Loads agent configuration from settings.json             │
└────────────────────┬────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│                    Agent Router                              │
│                                                              │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐     │
│  │ @coder       │  │ @writer      │  │ @assistant   │     │
│  │              │  │              │  │ (default)    │     │
│  │ Provider:    │  │ Provider:    │  │ Provider:    │     │
│  │ anthropic    │  │ openai       │  │ anthropic    │     │
│  │ Model:       │  │ Model:       │  │ Model:       │     │
│  │ sonnet       │  │ gpt-5.3-codex│  │ opus         │     │
│  │              │  │              │  │              │     │
│  │ Workspace:   │  │ Workspace:   │  │ Workspace:   │     │
│  │ ~/workspace/ │  │ ~/workspace/ │  │ ~/workspace/ │     │
│  │    coder/    │  │    writer/   │  │  assistant/  │     │
│  │              │  │              │  │              │     │
│  │ Config:      │  │ Config:      │  │ Config:      │     │
│  │ .claude/     │  │ .claude/     │  │ .claude/     │     │
│  │ heartbeat.md │  │ heartbeat.md │  │ heartbeat.md │     │
│  │ AGENTS.md    │  │ AGENTS.md    │  │ AGENTS.md    │     │
│  └──────────────┘  └──────────────┘  └──────────────┘     │
│                                                              │
│  Shared: ~/.tinyclaw/ (channels, files, logs, queue)       │
└─────────────────────────────────────────────────────────────┘
```

## How It Works


### 1. Message Routing


When a message arrives, the queue processor parses it for routing:

```typescript
// User sends: "@coder fix the authentication bug"
const routing = parseAgentRouting(rawMessage, agents);
// Result: { agentId: "coder", message: "fix the authentication bug" }
```

**Routing Rules:**
- Message starts with `@agent_id` → Routes to that agent
- No prefix → Routes to default agent (user-named during setup)
- Agent not found → Falls back to default agent
- No agents configured → Uses legacy single-agent mode

### 2. Agent Configuration


Each agent has its own configuration in `.tinyclaw/settings.json`:

```json
{
  "workspace": {
    "path": "/Users/me/tinyclaw-workspace",
    "name": "tinyclaw-workspace"
  },
  "agents": {
    "coder": {
      "name": "Code Assistant",
      "provider": "anthropic",
      "model": "sonnet",
      "working_directory": "/Users/me/tinyclaw-workspace/coder",
      "system_prompt": "You are a senior software engineer..."
    },
    "writer": {
      "name": "Technical Writer",
      "provider": "openai",
      "model": "gpt-5.3-codex",
      "working_directory": "/Users/me/tinyclaw-workspace/writer",
      "prompt_file": "/path/to/writer-prompt.md"
    },
    "assistant": {
      "name": "Assistant",
      "provider": "anthropic",
      "model": "opus",
      "working_directory": "/Users/me/tinyclaw-workspace/assistant"
    }
  }
}
```

**Note:** The `working_directory` is automatically set to `<workspace>/<agent_id>/` when creating agents via `tinyclaw.sh agent add`.

### 3. Agent Isolation


Each agent has its own isolated workspace directory with complete copies of configuration files:

**Agent Workspaces:**
```
~/tinyclaw-workspace/          # Or custom workspace name
├── coder/
│   ├── .claude/               # Agent's own Claude config
│   │   ├── settings.json
│   │   ├── settings.local.json
│   │   └── hooks/
│   │       ├── session-start.sh
│   │       └── log-activity.sh
│   ├── heartbeat.md           # Agent-specific heartbeat
│   ├── AGENTS.md              # Agent-specific docs
│   └── reset_flag             # Reset signal
├── writer/
│   ├── .claude/
│   ├── heartbeat.md
│   ├── AGENTS.md
│   └── reset_flag
└── assistant/                 # User-named default agent
    ├── .claude/
    ├── heartbeat.md
    ├── AGENTS.md
    └── reset_flag
```

**Templates & Shared Resources:**

Templates and shared resources are stored in `~/.tinyclaw/`:

```
~/.tinyclaw/
├── .claude/           # Template: Copied to each new agent
├── heartbeat.md       # Template: Copied to each new agent
├── AGENTS.md          # Template: Copied to each new agent
├── channels/          # SHARED: Channel state (QR codes, ready flags)
├── files/             # SHARED: Uploaded files from all channels
├── logs/              # SHARED: Log files for all agents and channels
└── queue/             # SHARED: Message queue (incoming/outgoing/processing)
```

**How it works:**
- Each agent runs CLI commands in its own workspace directory (`~/workspace/agent_id/`)
- Each agent gets its own copy of `.claude/`, `heartbeat.md`, and `AGENTS.md` from templates
- Agents can customize their settings, hooks, and documentation independently
- Conversation history is isolated per agent (managed by Claude/Codex CLI)
- Reset flags allow resetting individual agent conversations
- File operations happen in the agent's directory
- Templates stored in `~/.tinyclaw/` are copied when creating new agents
- Uploaded files, message queues, and logs are shared (common dependencies)

### 4. Provider Execution


The queue processor calls the appropriate CLI based on provider:

**Anthropic (Claude):**
```bash
cd "$agent_working_directory"  # e.g., ~/tinyclaw-workspace/coder/
claude --dangerously-skip-permissions \
  --model claude-sonnet-4-5 \
  --system-prompt "Your custom prompt..." \
  -c \  # Continue conversation
  -p "User message here"
```

**OpenAI (Codex):**
```bash
cd "$agent_working_directory"  # e.g., ~/tinyclaw-workspace/coder/
codex exec resume --last \
  --model gpt-5.3-codex \
  --skip-git-repo-check \
  --dangerously-bypass-approvals-and-sandbox \
  --json \
  "User message here"
```

## Configuration


### Initial Setup


During first-time setup (`./tinyclaw.sh setup`), you'll be prompted for:

1. **Workspace name** - Where to store agent directories
   - Default: `tinyclaw-workspace`
   - Creates: `~/tinyclaw-workspace/`

2. **Default agent name** - Name for your main assistant
   - Default: `assistant`
   - This replaces the hardcoded "default" agent

### Adding Agents


**Interactive CLI:**
```bash
./tinyclaw.sh agent add
```

This walks you through:
1. Agent ID (e.g., `coder`)
2. Display name (e.g., `Code Assistant`)
3. Provider (Anthropic or OpenAI)
4. Model selection
5. Optional system prompt

**Working directory is automatically set to:** `<workspace>/<agent_id>/`

**Manual Configuration:**

Edit `.tinyclaw/settings.json`:

```json
{
  "workspace": {
    "path": "/Users/me/tinyclaw-workspace",
    "name": "tinyclaw-workspace"
  },
  "agents": {
    "researcher": {
      "name": "Research Assistant",
      "provider": "anthropic",
      "model": "opus",
      "working_directory": "/Users/me/tinyclaw-workspace/researcher",
      "system_prompt": "You are a research assistant specialized in academic literature review and data analysis."
    }
  }
}
```

### Agent Fields


| Field | Required | Description |
|-------|----------|-------------|
| `name` | Yes | Human-readable display name |
| `provider` | Yes | `anthropic` or `openai` |
| `model` | Yes | Model identifier (e.g., `sonnet`, `opus`, `gpt-5.3-codex`) |
| `working_directory` | Yes | Directory where agent operates (auto-set to `<workspace>/<agent_id>/`) |
| `system_prompt` | No | Inline system prompt text |
| `prompt_file` | No | Path to file containing system prompt |

**Note:**
- If both `prompt_file` and `system_prompt` are provided, `prompt_file` takes precedence
- The `working_directory` is automatically set to `<workspace>/<agent_id>/` when creating agents
- Each agent gets its own isolated directory with copies of templates from `~/.tinyclaw/`

## Usage


### Routing Messages to Agents


**In any messaging channel** (Discord, Telegram, WhatsApp):

```
@coder fix the authentication bug in login.ts

@writer document the new API endpoints

@researcher find papers on transformer architectures

help me with this (goes to default agent - "assistant" by default)
```

### Listing Agents


**From chat:**
```
/agents
```

**From CLI:**
```bash
./tinyclaw.sh agent list
```

**Output:**
```
Configured Agents
==================

  @coder - Code Assistant
    Provider:  anthropic/sonnet
    Directory: /Users/me/tinyclaw-workspace/coder

  @writer - Technical Writer
    Provider:  openai/gpt-5.3-codex
    Directory: /Users/me/tinyclaw-workspace/writer
    Prompt:    /path/to/writer-prompt.md

  @assistant - Assistant
    Provider:  anthropic/opus
    Directory: /Users/me/tinyclaw-workspace/assistant
```

### Managing Agents


**Show agent details:**
```bash
./tinyclaw.sh agent show coder
```

**Reset agent conversation:**
```bash
./tinyclaw.sh agent reset coder
```

From chat:
```
@coder /reset
```

**Remove agent:**
```bash
./tinyclaw.sh agent remove coder
```

## Use Cases


### Specialized Codebases


Have different agents for different projects:

```json
{
  "workspace": {
    "path": "/Users/me/my-workspace"
  },
  "agents": {
    "frontend": {
      "working_directory": "/Users/me/my-workspace/frontend",
      "system_prompt": "You are a React and TypeScript expert..."
    },
    "backend": {
      "working_directory": "/Users/me/my-workspace/backend",
      "system_prompt": "You are a Node.js backend engineer..."
    }
  }
}
```

Usage:
```
@frontend add a loading spinner to the dashboard

@backend optimize the database queries in user service
```

### Role-Based Agents


Assign different roles to agents:

```json
{
  "agents": {
    "reviewer": {
      "system_prompt": "You are a code reviewer. Focus on security, performance, and best practices."
    },
    "debugger": {
      "system_prompt": "You are a debugging expert. Help identify and fix bugs systematically."
    },
    "architect": {
      "model": "opus",
      "system_prompt": "You are a software architect. Design scalable, maintainable systems."
    }
  }
}
```

### Provider Mixing


Use different AI providers for different tasks:

```json
{
  "agents": {
    "quick": {
      "provider": "anthropic",
      "model": "sonnet",
      "system_prompt": "Fast, efficient responses for quick questions."
    },
    "deep": {
      "provider": "anthropic",
      "model": "opus",
      "system_prompt": "Thorough, detailed analysis for complex problems."
    },
    "codegen": {
      "provider": "openai",
      "model": "gpt-5.3-codex",
      "system_prompt": "Code generation specialist."
    }
  }
}
```

## Advanced Features


### Dynamic Agent Routing


You can pre-route messages from channel clients by setting the `agent` field:

```typescript
// In channel client (discord-client.ts, etc.)
const queueData: QueueData = {
  channel: 'discord',
  message: userMessage,
  agent: 'coder',  // Pre-route to specific agent
  // ...
};
```

### Fallback Behavior


If no agents are configured, TinyClaw automatically creates a default agent using the legacy `models` section:

```json
{
  "models": {
    "provider": "anthropic",
    "anthropic": {
      "model": "sonnet"
    }
  }
}
```

This ensures backward compatibility with older configurations.

### Reset Flags


Two types of reset flags:

1. **Global reset:** `~/.tinyclaw/reset_flag` - resets all agents
2. **Per-agent reset:** `<workspace>/<agent_id>/reset_flag` - resets specific agent

Both are automatically cleaned up after use.

### Custom Workspaces


You can create multiple workspaces for different purposes:

```json
{
  "workspace": {
    "path": "/Users/me/work-projects",
    "name": "work-projects"
  }
}
```

Or even use cloud-synced directories:
```json
{
  "workspace": {
    "path": "/Users/me/Dropbox/tinyclaw-workspace",
    "name": "tinyclaw-workspace"
  }
}
```

## File Handling


Files uploaded through messaging channels are automatically available to all agents:

```
User uploads image.png via Telegram
→ Saved to ~/.tinyclaw/files/telegram_123456_image.png
→ Message includes: [file: /path/to/image.png]
→ Routed to agent
→ Agent can read/process the file
```

Agents can also send files back:

```typescript
// Agent response includes:
response = "Here's the diagram [send_file: /path/to/diagram.png]";
// File is extracted and sent back through channel
```

## Troubleshooting


For detailed troubleshooting of agent-related issues, see [TROUBLESHOOTING.md](TROUBLESHOOTING.md).

**Quick reference:**

- **Agent not found** → Check: `tinyclaw agent list`
- **Wrong agent responding** → Verify routing: `@agent_id message` (with space)
- **Conversation not resetting** → Send message after: `tinyclaw agent reset <id>`
- **CLI not found** → Install Claude Code or Codex CLI
- **Workspace issues** → Check: `cat .tinyclaw/settings.json | jq '.workspace'`
- **Templates not copying** → Run: `tinyclaw setup`

## Implementation Details


### Code Structure


**Queue Processor** (`src/queue-processor.ts`):
- `getSettings()` - Loads settings from JSON
- `getAgents()` - Returns agent configurations (checks `.agents`)
- `parseAgentRouting()` - Parses @agent_id prefix
- `processMessage()` - Main routing and execution logic

**Message Interfaces:**
```typescript
interface MessageData {
  agent?: string;      // Pre-routed agent ID
  files?: string[];    // Uploaded file paths
  // ...
}

interface ResponseData {
  agent?: string;      // Which agent handled this
  files?: string[];    // Files to send back
  // ...
}
```

### Agent Directory Structure


**Templates:**
```
~/.tinyclaw/
├── .claude/           # Copied to new agents
├── heartbeat.md       # Copied to new agents
└── AGENTS.md          # Copied to new agents
```

**Agent State:**
```
<workspace>/
└── {agent_id}/
    ├── .claude/       # Agent's own config
    ├── heartbeat.md   # Agent's own monitoring
    ├── AGENTS.md      # Agent's own docs
    └── reset_flag     # Touch to reset conversation
```

State is managed by the CLI itself (claude or codex) through the `-c` flag and working directory isolation.

## Future Enhancements


Potential features for agent management:

- **Agent delegation:** Agents can call other agents
- **Shared context:** Optional shared memory between agents
- **Agent scheduling:** Time-based or event-based agent activation
- **Agent groups:** Organize agents into hierarchies
- **Web dashboard:** Visual agent management and monitoring
- **Agent analytics:** Track usage, performance per agent
- **Workspace templates:** Pre-configured agent workspaces for common use cases
- **Agent migration:** Export/import agent configurations

## See Also


- [README.md]../README.md - Main project documentation
- Setup wizard: `./tinyclaw.sh setup`
- Agent CLI: `./tinyclaw.sh agent --help`