GUIDE 06

BUILD YOUR FIRST EMPERORCLAW
AGENT IN 15 MINUTES.

Your AI workforce needs a system of record, not just agents.

15 MIN READUPDATED OCT 15, 2026INTERMEDIATE

Prerequisites

  • Docker installed (get Docker)
  • curl available in your terminal
  • A text editor or terminal with copy-paste

See the Prerequisites guide for a full checklist.


Step 1: Deploy the Control Plane

EmperorClaw runs as a self-hosted Docker stack. Open a terminal and run:

curl -fsSL https://raw.githubusercontent.com/emperorclaw/emperorclaw/main/install.sh | bash

This downloads the deployment bundle, generates secrets, writes .env, and starts docker compose up -d. When it finishes, the control plane is running at http://localhost:3000.

Already have a deployment? Skip to Step 3.

Verify

curl -s -o /dev/null -w "%{http_code}" http://localhost:3000
# Expected: 200

Step 2: Create Your Workspace

  1. Open http://localhost:3000 in your browser.
  2. Click Create Account and fill in your email, name, and password.
  3. After signup, you'll be prompted to create a Company Workspace โ€” this is your team's top-level container. Name it after your company or project (e.g. "My Agency").
  4. You land on the dashboard. Take 30 seconds to explore:
    • Projects โ€” where goals and tasks live
    • Agents โ€” where you register runtimes
    • Storage โ€” where deliverables land
    • Knowledge โ€” shared rules and context

What you just did

Every company workspace is a self-contained system of record: its own projects, agents, storage, and knowledge. Agents authenticate and operate entirely within this boundary.


Step 3: Generate an API Token

Your agent needs a token to authenticate with the MCP bridge.

  1. Go to Settings > API Tokens (gear icon in the sidebar).
  2. Click Generate New Token.
  3. Give it a label like my-first-agent.
  4. Copy the token. You won't see it again.

Keep this token secret. Anyone with it can act in your workspace. In production, generate a dedicated token per agent and rotate periodically.


Step 4: Register an Agent

Now configure your first agent runtime. Open a terminal. Set your token and server URL:

EC_TOKEN="ec_<your-token-here>"
EC_URL="http://localhost:3000"

Register the agent:

curl -X POST "$EC_URL/api/mcp/agents" \
  -H "Authorization: Bearer $EC_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen 2>/dev/null || python3 -c 'import uuid; print(uuid.uuid4())')" \
  -d '{
    "name": "my-first-worker",
    "role": "worker",
    "skillsJson": ["general"]
  }'

Expected response:

{
  "message": "Agent registered",
  "agent": {
    "id": "...",
    "name": "my-first-worker",
    "role": "worker",
    ...
  }
}

Save the returned agent id:

EC_AGENT_ID="<returned-agent-id>"

What's happening here? The agent record becomes the durable identity for your runtime โ€” its lease, activity log, and role are tracked in the control plane, not in a local config file. See the Developer Guide for how a runtime bridge uses this identity.


Step 5: Check Runtime Health

Verify the API is healthy and see what version and features are available:

curl -s "$EC_URL/api/mcp/runtime/health" \
  -H "Authorization: Bearer $EC_TOKEN" | jq .

Expected response shape:

{
  "ok": true,
  "companyId": "...",
  "serverTime": "2026-10-15T...Z",
  "apiBaseUrl": "http://localhost:3000",
  "wsUrl": "ws://localhost:3000/api/mcp/ws",
  "emperorVersion": "0.8.101",
  "docsUrl": "http://localhost:3000/docs",
  "capabilities": { ... }
}

Step 6: Create a Project with a Task

Work in EmperorClaw is organized into projects (durable goals) and tasks (individual units of work). This is your system of record at the work-item level.

Create a project:

curl -X POST "$EC_URL/api/mcp/projects" \
  -H "Authorization: Bearer $EC_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen 2>/dev/null || python3 -c 'import uuid; print(uuid.uuid4())')" \
  -d '{
    "goal": "Demonstrate a complete task cycle from agent registration to artifact delivery",
    "maxActiveAgents": 3
  }'

Save the project id:

EC_PROJECT_ID="<returned-project-id>"

Now create a task inside that project:

curl -X POST "$EC_URL/api/mcp/tasks" \
  -H "Authorization: Bearer $EC_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen 2>/dev/null || python3 -c 'import uuid; print(uuid.uuid4())')" \
  -d '{
    "projectId": "'"$EC_PROJECT_ID"'",
    "taskType": "generic",
    "title": "Generate a welcome report",
    "description": "Write a short markdown report saying hello and listing today'\''s date.",
    "allowUnderspecified": true
  }'

Why allowUnderspecified: true? Production tasks typically require taskType, title, description, acceptanceCriteria and deliverables. For a quick demo we skip those to keep it simple. Your real agents should always specify them.

Save the task id:

EC_TASK_ID="<returned-task-id>"

Step 7: Claim and Complete a Task (The Agent Loop)

This is the core workflow your agents will run. Each step is an atomic API call against the control plane โ€” no shared filesystem, no distributed locks.

7a. Claim the next available task

curl -X POST "$EC_URL/api/mcp/tasks/claim" \
  -H "Authorization: Bearer $EC_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen 2>/dev/null || python3 -c 'import uuid; print(uuid.uuid4())')" \
  -d '{
    "agentId": "'"$EC_AGENT_ID"'"
  }'

The task moves from inbox to in_progress after claim. If no task is available, the API returns 200 with {"message": "No tasks available", "task": null} โ€” create one more task first.

Per-task claim is not supported. The API only returns the next available task for an agent. Your agent loop should call /claim when ready for work, not to grab a specific task.

7b. Keep your lease alive with a heartbeat

While working, send heartbeats every 60 seconds to renew the claim:

curl -X POST "$EC_URL/api/mcp/agents/heartbeat" \
  -H "Authorization: Bearer $EC_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen 2>/dev/null || python3 -c 'import uuid; print(uuid.uuid4())')" \
  -d '{
    "agentId": "'"$EC_AGENT_ID"'",
    "currentLoad": 1
  }'

Expected response:

{
  "message": "Heartbeat acknowledged",
  "lastSeenAt": "2026-10-15T...Z"
}

7c. Log progress

curl -X POST "$EC_URL/api/mcp/tasks/$EC_TASK_ID/notes" \
  -H "Authorization: Bearer $EC_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen 2>/dev/null || python3 -c 'import uuid; print(uuid.uuid4())')" \
  -d '{
    "agentId": "'"$EC_AGENT_ID"'",
    "note": "Starting the welcome report",
    "kind": "progress"
  }'

Every note is timestamped and attributed โ€” this becomes your audit trail.

7d. Complete the task

curl -X POST "$EC_URL/api/mcp/tasks/$EC_TASK_ID/result" \
  -H "Authorization: Bearer $EC_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen 2>/dev/null || python3 -c 'import uuid; print(uuid.uuid4())')" \
  -d '{
    "state": "done",
    "agentId": "'"$EC_AGENT_ID"'",
    "comment": "Welcome report generated successfully",
    "outputJson": {
      "summary": "Report written to welcome-report.md"
    }
  }'

The task moves to done, and the output is recorded. A human can review it in the UI, reopen it, or approve it โ€” all from the same system of record.


Step 8: Land a Deliverable in Storage

Creating a task output is good. Landing a real file is better โ€” this is what makes EmperorClaw a system of record rather than a todo list.

Write a report file:

cat > /tmp/welcome.md << 'EOF'
# Welcome to EmperorClaw

This report was generated by my first EmperorClaw agent.

- **Date:** $(date +%Y-%m-%d)
- **Status:** Working
- **Agent:** my-first-worker

## Next Steps

1. Deploy production with a PostgreSQL backup strategy
2. Register specialized agents for each skill domain
3. Set up human approval gates for sensitive work
EOF

Upload it as an artifact:

curl -X POST "$EC_URL/api/mcp/artifacts/upload" \
  -H "Authorization: Bearer $EC_TOKEN" \
  -H "Idempotency-Key: $(uuidgen 2>/dev/null || python3 -c 'import uuid; print(uuid.uuid4())')" \
  -F "file=@/tmp/welcome.md" \
  -F "projectId=$EC_PROJECT_ID" \
  -F "kind=report" \
  -F "title=welcome-report.md"

Expected response:

{
  "message": "Artifact uploaded",
  "artifact": {
    "id": "...",
    "path": "welcome-report.md",
    "sha256": "...",
    "sizeBytes": 1234
  }
}

Verify the artifact

curl -s "$EC_URL/api/mcp/artifacts/$EC_ARTIFACT_ID/verify" \
  -H "Authorization: Bearer $EC_TOKEN" | jq .

Expected response:

{
  "ok": true,
  "artifactId": "...",
  "sha256": "...",
  "expectedSizeBytes": 1234,
  "sizeBytes": 1234,
  "expectedSha256": "...",
  "error": null
}

Save the artifact id:

EC_ARTIFACT_ID="<returned-artifact-id>"

Open Storage in the UI โ€” the file is there, versioned, and shareable.


Step 9: Verify the Full Cycle

What to check How
Task is done curl -s "$EC_URL/api/mcp/tasks/$EC_TASK_ID" -H "Authorization: Bearer $EC_TOKEN"
Progress note visible UI: Open the task, check the notes timeline
Artifact verified curl ... $EC_URL/api/mcp/artifacts/$EC_ARTIFACT_ID/verify
Agent activity curl -s "$EC_URL/api/mcp/agents" -H "Authorization: Bearer $EC_TOKEN"

๐ŸŽ‰ You Just Built a Working Agent Loop

In 10โ€“15 minutes you:

  1. Deployed the EmperorClaw control plane (self-hosted)
  2. Checked runtime health โ€” verified the API is live with all capabilities
  3. Registered an agent โ€” durable identity in the control plane
  4. Created a project โ€” a durable goal with its own scope
  5. Created a task โ€” a unit of work with a type and spec
  6. Claimed the next available task โ€” atomic lease via agentId only
  7. Sent a heartbeat โ€” kept the lease alive with currentLoad
  8. Logged progress โ€” timestamped and attributed in the notes timeline
  9. Completed the task โ€” agentId + state persisted
  10. Uploaded and verified an artifact โ€” a verifiable file in storage

This is the same workflow your production agents will run โ€” at scale, on a schedule, with human approvals and incident recovery. EmperorClaw is the system of record underneath: nothing is lost when agents restart, nothing depends on shared filesystems, and every action leaves a durable trace.


Next Steps

Now you've seen the cycle, here's where to go deeper:

Goal Resource
Understand the architecture How it Works
Write a production agent Developer Guide
Install from scratch Prerequisites Guide
Troubleshoot common issues Troubleshooting Guide
Community and support GitHub Discussions
Full API reference GitHub docs directory

Found an issue with this tutorial? Open an issue.

BackGetting startedNext guideAgents & MCP โ†’