@artyfacts/clawdbot-adapter
v1.0.0
Published
Clawdbot adapter for Artyfacts SDK - enables AI agents to interact with Artyfacts through Clawdbot tools
Downloads
60
Maintainers
Readme
@artyfacts/clawdbot-adapter
Bridge AI agents running in Clawdbot to the Artyfacts task queue. This adapter polls for pending tasks, spawns sub-agents to work on them, detects completions, and cascades to unblocked follow-up tasks automatically.
Table of Contents
- What is this?
- Installation
- Quick Start
- Configuration
- Commands
- How it Works
- API Reference
- Troubleshooting
- Contributing
What is this?
Problem: You have AI agents running in Clawdbot, and you have tasks defined in Artyfacts (specs, goals, experiments). How do you connect them?
Solution: This adapter continuously polls the Artyfacts task queue, claims work for your agent, spawns sub-agents via Clawdbot Gateway to do the work, and automatically cascades to dependent tasks when work completes.
Key Features
- 🔄 Continuous Polling — Watches the Artyfacts queue for claimable tasks
- 🤖 Auto-Spawning — Spawns sub-agents via Clawdbot Gateway to work on tasks
- 🔗 Dependency Cascading — Completes a task → unblocks dependents → spawns agents for them
- 💾 Crash Recovery — Persists state; resumes gracefully after restarts
- ⚙️ Daemon Mode — Run as a background service with logs and status monitoring
Installation
npm install @artyfacts/clawdbot-adapterOr with your preferred package manager:
pnpm add @artyfacts/clawdbot-adapter
yarn add @artyfacts/clawdbot-adapterRequirements
- Node.js 18+
- Running Clawdbot Gateway (default:
http://localhost:3001) - Artyfacts API key
Quick Start
1. Run the Setup Wizard
npx clawdbot-artyfacts initThis interactive wizard:
- Prompts for your Artyfacts API key
- Validates connectivity to the Artyfacts API
- Detects your Clawdbot Gateway URL
- Creates
~/.artyfacts/adapter.json
2. Start the Adapter
# Foreground (see output directly)
npx clawdbot-artyfacts start
# Background daemon (recommended for production)
npx clawdbot-artyfacts start -d3. Monitor Activity
# Check status
npx clawdbot-artyfacts status
# View logs
npx clawdbot-artyfacts logs -f4. Stop When Done
npx clawdbot-artyfacts stopConfiguration
Configuration is loaded from multiple sources (highest priority first):
- Command-line flags (e.g.,
-i 5m) - Environment variables (e.g.,
ARTYFACTS_API_KEY) - Config file (
~/.artyfacts/adapter.json) - Schema defaults
Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| ARTYFACTS_API_KEY | Your Artyfacts API key | required |
| ARTYFACTS_BASE_URL | Artyfacts API base URL | https://artyfacts.dev/api/v1 |
| CLAWDBOT_GATEWAY_URL | Clawdbot Gateway URL | http://localhost:3001 |
| CLAWDBOT_AUTH_TOKEN | Gateway auth token (if required) | none |
| ADAPTER_POLLING_INTERVAL | How often to poll (e.g., 30s, 5m) | 30s |
| ADAPTER_MAX_CONCURRENT | Max simultaneous tasks | 3 |
Config File
Create ~/.artyfacts/adapter.json:
{
"artyfacts": {
"apiKey": "sk_...",
"baseUrl": "https://artyfacts.dev/api/v1"
},
"clawdbot": {
"gatewayUrl": "http://localhost:3001",
"authToken": null
},
"polling": {
"interval": "30s",
"maxConcurrent": 3
}
}Configuration Reference
artyfacts
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| apiKey | string | ✅ | Your Artyfacts API key (starts with sk_) |
| baseUrl | string | ❌ | API endpoint. Default: https://artyfacts.dev/api/v1 |
clawdbot
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| gatewayUrl | string | ❌ | Clawdbot Gateway WebSocket URL. Default: http://localhost:3001 |
| authToken | string | ❌ | Authentication token if gateway requires auth |
polling
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| interval | string | ❌ | Poll frequency. Format: <number><unit> where unit is s/m/h. Default: 30s |
| maxConcurrent | number | ❌ | Maximum tasks to work simultaneously (1-10). Default: 3 |
Validate Your Config
npx clawdbot-artyfacts validateExample output:
✅ Configuration valid
Sources:
📁 Config file: ~/.artyfacts/adapter.json
🌍 Environment: ARTYFACTS_API_KEY
Settings:
Artyfacts API: https://artyfacts.dev/api/v1
Gateway: http://localhost:3001
Polling: every 30s, max 3 concurrentCommands
init — Interactive Setup
npx clawdbot-artyfacts initWalks you through configuration:
- Enter your Artyfacts API key
- Validates the key against the API
- Auto-detects Clawdbot Gateway
- Saves to
~/.artyfacts/adapter.json
start — Start Polling
npx clawdbot-artyfacts start [options]Options:
| Flag | Description |
|------|-------------|
| -d, --daemon | Run as a background process |
| -i, --interval <time> | Override poll interval (e.g., 30s, 5m, 1h) |
| -c, --concurrent <n> | Override max concurrent tasks (1-10) |
| -a, --agent <id> | Agent ID for claiming tasks |
Examples:
# Foreground with 5-minute polling
npx clawdbot-artyfacts start -i 5m
# Daemon with custom concurrency
npx clawdbot-artyfacts start -d -c 5
# Specific agent identity
npx clawdbot-artyfacts start -a engineering-agentstatus — View Current State
npx clawdbot-artyfacts status [options]Options:
| Flag | Description |
|------|-------------|
| -j, --json | Output as JSON (for scripting) |
Example output:
📊 Artyfacts Adapter Status
● Running (PID: 12345)
Daemon Info:
Started: 5m ago
Last poll: just now
Polls: 10
Tasks claimed: 3
Tasks done: 2
Interval: 30s
Max concurrent: 3
Active Tasks (1):
🔄 task-implement-feature
Artifact: abc123
Started: 2m ago
Agent: engineering-agent
Configuration:
✅ Valid
Sources: config file, environmentstop — Stop the Daemon
npx clawdbot-artyfacts stop [options]Options:
| Flag | Description |
|------|-------------|
| -f, --force | Force kill (SIGKILL instead of SIGTERM) |
logs — View Activity Logs
npx clawdbot-artyfacts logs [options]Options:
| Flag | Description |
|------|-------------|
| -n, --lines <n> | Number of lines to show (default: 50) |
| -f, --follow | Stream logs in real-time (like tail -f) |
Examples:
# Last 100 lines
npx clawdbot-artyfacts logs -n 100
# Stream live
npx clawdbot-artyfacts logs -fconfig — Show Configuration
npx clawdbot-artyfacts configDisplays the current merged configuration (file + env), with sensitive values masked.
validate — Validate Configuration
npx clawdbot-artyfacts validateChecks all config sources and reports any errors or missing values.
How it Works
Architecture Overview
┌─────────────────────────────────────────────────────────────────────┐
│ ARTYFACTS CLOUD │
│ ┌──────────────┐ ┌──────────────┐ ┌───────────────────────┐ │
│ │ Task Queue │ │ Artifacts │ │ Dependency Tracker │ │
│ │ (pending) │◄───│ (specs, │ │ (blocked/unblocked) │ │
│ │ │ │ goals) │ │ │ │
│ └──────┬───────┘ └──────────────┘ └───────────┬───────────┘ │
└─────────│────────────────────────────────────────────│──────────────┘
│ poll │ unblock
▼ │
┌─────────────────────────────────────────────────────────────────────┐
│ CLAWDBOT-ADAPTER (this package) │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ TaskPoller │───►│ TaskSpawner │───►│ CompletionHandler │ │
│ │ │ │ │ │ │ │
│ │ • Poll API │ │ • Format │ │ • Parse "✅ Done!" │──┼──┐
│ │ • Claim │ │ prompt │ │ • Call complete API │ │ │
│ │ • Dedupe │ │ • Spawn via │ │ • Spawn unblocked tasks │◄─┼──┘
│ │ │ │ Gateway │ │ │ │
│ └─────────────┘ └──────┬──────┘ └─────────────────────────┘ │
│ │ │
│ ┌─────────────────────────┼───────────────────────────────────┐ │
│ │ StateManager (crash recovery) │ │
│ │ • Active tasks • Completions • Recovery on restart │ │
│ └─────────────────────────────────────────────────────────────┘ │
└────────────────────────────│────────────────────────────────────────┘
│ spawn request
▼
┌─────────────────────────────────────────────────────────────────────┐
│ CLAWDBOT GATEWAY │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ WebSocket API │ │ Session Manager │ │ LLM Provider │ │
│ │ │───►│ │───►│ (Claude, etc.) │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘Data Flow
1. POLL TaskPoller hits GET /tasks/queue
─────────────────────────────────► Artyfacts API
2. CLAIM TaskPoller claims task (POST /tasks/:id/claim)
─────────────────────────────────► Artyfacts API
3. SPAWN TaskSpawner formats prompt, sends to Gateway
─────────────────────────────────► Clawdbot Gateway
└─► Spawns sub-agent
4. WORK Sub-agent does the work
─────────────────────────────────► (writes code, research, etc.)
5. COMPLETE Sub-agent reports: "✅ Done! Task: task-123 Output: PR#456"
◄───────────────────────────────── Sub-agent message
6. FINALIZE CompletionHandler calls POST /tasks/:id/complete
─────────────────────────────────► Artyfacts API
└─► Returns unblocked tasks
7. CASCADE Spawn new agents for unblocked tasks
─────────────────────────────────► Loop back to step 3Component Details
TaskPoller
- Polls
/tasks/queueat the configured interval - Respects
maxConcurrent— won't claim more than N tasks at once - Dedupes tasks already being worked (via StateManager)
- Emits
task:claimedevents
TaskSpawner
- Formats tasks into structured prompts for sub-agents
- Includes artifact context, dependencies, expected output format
- Spawns via Clawdbot Gateway WebSocket API
- Tracks spawned sessions for correlation
CompletionHandler
- Detects the completion pattern in agent messages:
✅ Done! Task: <task-id> Output: <url or description> - Calls the Artyfacts complete API
- Receives list of newly-unblocked tasks
- Triggers spawns for follow-up work
StateManager
- Persists active tasks to
~/.artyfacts/state.json - On restart: reconciles state with Artyfacts API
- Handles edge cases (task completed while adapter was down, etc.)
File Locations
| File | Purpose |
|------|---------|
| ~/.artyfacts/adapter.json | Configuration |
| ~/.artyfacts/adapter.pid | Daemon process ID |
| ~/.artyfacts/adapter.log | Daemon activity log |
| ~/.artyfacts/state.json | Active task state (for recovery) |
API Reference
Programmatic Usage
import { ClawdbotAdapter } from '@artyfacts/clawdbot-adapter';
const adapter = new ClawdbotAdapter(
async (toolName, params) => {
// Your Clawdbot tool invocation logic
return { success: true, data: result };
},
{
apiKey: process.env.ARTYFACTS_API_KEY,
agentId: 'my-agent',
agentName: 'My Agent',
}
);
// Create an artifact
const artifact = await adapter.createArtifact({
title: 'Research Report',
content: '# Findings\n\nMy research...',
tags: ['research'],
});Core Classes
ArtyfactsClient
HTTP client for Artyfacts task operations.
import { ArtyfactsClient } from '@artyfacts/clawdbot-adapter';
const client = new ArtyfactsClient({
apiKey: 'sk_...',
baseUrl: 'https://artyfacts.dev/api/v1',
});
// Get pending tasks
const tasks = await client.getTaskQueue({ limit: 10 });
// Claim a task
const claimed = await client.claimTask('task-123', 'my-agent');
// Complete a task
const result = await client.completeTask('task-123', {
url: 'https://github.com/...',
summary: 'PR merged',
});
// result.unblockedTasks → tasks that are now readyClawdbotClient
WebSocket client for Clawdbot Gateway.
import { ClawdbotClient } from '@artyfacts/clawdbot-adapter';
const client = new ClawdbotClient({
gatewayUrl: 'http://localhost:3001',
});
await client.connect();
// Spawn a sub-agent
const result = await client.spawnAgent({
task: 'Research competitors...',
label: 'research-task',
model: 'claude-sonnet-4-20250514',
});
// Wait for completion
const outcome = await client.waitForRun(result.runId, 300000);
client.disconnect();TaskPoller
Event-based task polling.
import { TaskPoller } from '@artyfacts/clawdbot-adapter';
const poller = new TaskPoller(artyfactsClient, stateManager, {
interval: '30s',
maxConcurrent: 3,
agentId: 'my-agent',
});
poller.on('task:claimed', (task) => {
console.log(`Claimed: ${task.id}`);
});
poller.on('poll:error', (error) => {
console.error('Poll failed:', error.message);
});
poller.start();TaskSpawner
Spawns sub-agents for tasks.
import { TaskSpawner } from '@artyfacts/clawdbot-adapter';
const spawner = new TaskSpawner({
client: clawdbotClient,
stateManager,
});
const result = await spawner.spawn(task, {
agentId: 'engineering-agent',
model: 'claude-sonnet-4-20250514',
});CompletionHandler
Detects and processes completions.
import { CompletionHandler, parseCompletion } from '@artyfacts/clawdbot-adapter';
// Quick check
const parsed = parseCompletion(agentMessage);
if (parsed.detected) {
console.log(`Task completed: ${parsed.taskId}`);
}
// Full processing
const handler = new CompletionHandler({
artyfactsClient,
taskSpawner,
stateManager,
});
const result = await handler.process(agentMessage);
if (result.success) {
console.log(`Spawned ${result.spawnedTasks.length} follow-ups`);
}StateManager
Persistent state for crash recovery.
import { StateManager } from '@artyfacts/clawdbot-adapter';
const state = new StateManager();
await state.load();
// Track a new task
state.trackTask({
taskId: 'task-123',
artifactId: 'abc',
sessionKey: 'session-456',
startedAt: new Date().toISOString(),
});
// On completion
state.completeTask('task-123', {
outputUrl: 'https://...',
completedAt: new Date().toISOString(),
});
// Crash recovery
const recovered = await state.recover(async (taskId) => {
return await artyfactsClient.getTaskStatus(taskId);
});Troubleshooting
Common Errors
"Configuration validation failed: artyfacts.apiKey is required"
Cause: No API key provided.
Fix:
# Option 1: Set environment variable
export ARTYFACTS_API_KEY="sk_..."
# Option 2: Run setup wizard
npx clawdbot-artyfacts init"Failed to connect to Clawdbot Gateway"
Cause: Gateway not running or wrong URL.
Fix:
- Ensure Clawdbot is running:
clawdbot gateway status - Start if needed:
clawdbot gateway start - Check URL in config matches actual gateway port
"Task already claimed by another agent"
Cause: Race condition — another adapter instance claimed the task first.
Fix: This is normal in multi-agent setups. The adapter will skip and try the next task.
"ECONNREFUSED 127.0.0.1:3001"
Cause: Clawdbot Gateway not running.
Fix:
clawdbot gateway start"Invalid API key"
Cause: API key is malformed or revoked.
Fix:
- Get a new key from https://artyfacts.dev/settings/api-keys
- Update your config:
npx clawdbot-artyfacts init
"Poll error: NetworkError"
Cause: Network issue connecting to Artyfacts API.
Fix:
- Check internet connectivity
- Verify
ARTYFACTS_BASE_URLis correct - Check https://status.artyfacts.dev for outages
Debugging
Enable Verbose Logging
DEBUG=adapter:* npx clawdbot-artyfacts startCheck Daemon Status
npx clawdbot-artyfacts status -j | jq .View Full Logs
cat ~/.artyfacts/adapter.logInspect State File
cat ~/.artyfacts/state.json | jq .Reset State (Nuclear Option)
# Stop the adapter
npx clawdbot-artyfacts stop
# Clear state
rm ~/.artyfacts/state.json
# Restart
npx clawdbot-artyfacts start -dGetting Help
- Check the logs:
npx clawdbot-artyfacts logs -n 200 - Validate config:
npx clawdbot-artyfacts validate - File an issue: https://github.com/artygroup/artyfacts/issues
Contributing
Development Setup
# Clone the repo
git clone https://github.com/artygroup/artyfacts.git
cd artyfacts/packages/clawdbot-adapter
# Install dependencies
npm install
# Build
npm run build
# Run tests
npm test
# Lint
npm run lint
# Format
npm run format
# Type check
npm run typecheckProject Structure
src/
├── cli/ # CLI commands
│ ├── index.ts # Command definitions
│ ├── init.ts # Setup wizard
│ ├── start.ts # Start command
│ ├── status.ts # Status command
│ ├── stop.ts # Stop command
│ ├── logs.ts # Logs command
│ ├── commands.ts # Config/validate commands
│ └── daemon.ts # Daemon management
├── adapter.ts # Main adapter class
├── artyfacts-client.ts # Artyfacts HTTP client
├── clawdbot-client.ts # Clawdbot WebSocket client
├── poller.ts # Task polling
├── spawner.ts # Sub-agent spawning
├── completer.ts # Completion detection
├── config.ts # Configuration loading
├── state.ts # State management
├── tools.ts # Tool wrappers
├── types.ts # Type definitions
└── index.ts # Public exportsRunning Tests
# All tests
npm test
# Watch mode
npm test -- --watch
# Coverage
npm test -- --coverageMaking a PR
- Fork the repo
- Create a feature branch:
git checkout -b feat/my-feature - Make your changes
- Run tests:
npm test - Run lint:
npm run lint - Commit with conventional commits:
git commit -m "feat: add thing" - Push and open a PR
License
MIT © Artygroup
