Skip to content

Instantly share code, notes, and snippets.

@ajsharp
Created February 12, 2026 15:36
Show Gist options
  • Select an option

  • Save ajsharp/ebcd117e2740f3ee0ad7d9c6f367ebbf to your computer and use it in GitHub Desktop.

Select an option

Save ajsharp/ebcd117e2740f3ee0ad7d9c6f367ebbf to your computer and use it in GitHub Desktop.
OpenClaw Agent Management and Autonomy Patterns

OpenClaw Agent Management and Autonomy Patterns

Generated: 2026-02-11 Source: Research for issue conductorbot-6cr

Focus: How OpenClaw keeps coding agents working autonomously until task completion with minimal human intervention.


Key Insight

OpenClaw achieves autonomy through prompt engineering, heartbeat polling, and sub-agent delegation - NOT through complex supervisor logic or confidence thresholds.

The pattern: "Just do it, don't ask" combined with periodic heartbeat checks for new work.


1. Agent Prompting and Guidance

System Prompt Structure

File: /Users/ajsharp/code/github/openclaw/src/agents/system-prompt.ts (~650 lines)

Key sections that drive autonomy:

"## Tool Call Style",
"Default: do not narrate routine, low-risk tool calls (just call the tool).",
"Narrate only when it helps: multi-step work, complex/challenging problems,
 sensitive actions (e.g., deletions), or when the user explicitly asks.",
"Keep narration brief and value-dense; avoid repeating obvious steps.",

Pattern: Explicitly tells agents to act without asking permission for routine operations.

Heartbeat System

File: /Users/ajsharp/code/github/openclaw/src/auto-reply/heartbeat.ts

export const HEARTBEAT_PROMPT =
  "Read HEARTBEAT.md if it exists (workspace context). Follow it strictly.
   Do not infer or repeat old tasks from prior chats.
   If nothing needs attention, reply HEARTBEAT_OK.";

How it works:

  1. Poll agent every 30 minutes (configurable)
  2. Check HEARTBEAT.md for pending tasks
  3. If agent responds "HEARTBEAT_OK" → discard, no user notification
  4. If agent has content → deliver to user

Result: Creates continuous background loop where agents autonomously pick up work.


2. Autonomy vs User Input Decision-Making

OpenClaw shapes agent behavior through prompting rather than filtering questions:

No Central Question Filter

  • No "should I ask the user?" confidence thresholds
  • No question interception middleware
  • Instead: prompt engineering tells agents when to narrate vs act

Sub-Agent Delegation Pattern

File: /Users/ajsharp/code/github/openclaw/src/agents/tools/sessions-spawn-tool.ts

"Spawn a background sub-agent run in an isolated session
 and announce the result back to the requester chat."

Flow:

  1. Main agent spawns sub-agent with task description
  2. Sub-agent works in isolated session
  3. Sub-agent announces completion back to main session
  4. Main agent sees result and decides next steps

Why this works:

  • Complex work delegated to isolated sub-agents
  • Main agent stays responsive
  • Sub-agents can fail/retry without blocking main agent

3. Task Completion Detection

Completion Signals

File: /Users/ajsharp/code/github/openclaw/src/agents/pi-embedded-runner/run.ts

return {
  payloads: [...],
  meta: {
    durationMs,
    agentMeta: { sessionId, provider, model, usage },
    aborted,
    stopReason: attempt.clientToolCall ? "tool_calls" : undefined,
  },
};

Stop reasons:

  1. "end_turn" - Agent finished response
  2. "tool_calls" - Agent made tool call (waiting for result)
  3. "error" - Agent encountered error
  4. "aborted" - User/system aborted

Silent Tokens

File: /Users/ajsharp/code/github/openclaw/src/auto-reply/tokens.ts

export const SILENT_REPLY_TOKEN = "SILENT_REPLY";
export const HEARTBEAT_TOKEN = "HEARTBEAT_OK";

// Agent can signal "nothing to say" without user notification
if (reply === "HEARTBEAT_OK" || reply === SILENT_REPLY_TOKEN) {
  // Don't deliver to user
}

Pattern: Agent explicitly signals when it has nothing to report.

No Explicit "Done" Tool

Completion is inferred from:

  • Agent stops generating (end_turn)
  • Agent returns heartbeat ack (HEARTBEAT_OK)
  • Agent returns silent token (SILENT_REPLY_TOKEN)
  • Sub-agent announces result back to parent

4. Meta-Agent / Supervisor Patterns

Peer-to-Peer Coordination (Not Centralized Supervisor)

Sub-agent Registry (/Users/ajsharp/code/github/openclaw/src/agents/subagent-registry.ts):

registerSubagentRun({
  runId: childRunId,
  childSessionKey,
  requesterSessionKey: requesterInternalKey,
  requesterOrigin,
  task,
  cleanup,
  label,
  runTimeoutSeconds,
});

Pattern:

  1. Main agent delegates work via sessions_spawn tool
  2. Child session runs in background with isolated state
  3. Child announces result back to parent via delivery config
  4. Parent sees announcement and continues

Sub-agent System Prompt:

export function buildSubagentSystemPrompt(params: {
  requesterSessionKey?: string;
  task: string;
}): string {
  return `## Subagent Context
You are running as a sub-agent spawned by ${params.requesterSessionKey}.
Your task: ${params.task}
When complete, results will be announced back to the requester.`;
}

Key: No centralized supervisor - coordination is peer-to-peer via sessions and announcements.


5. Single-Agent Loop (Ralph Loop Pattern)

Agent Runner Retry Loop

File: /Users/ajsharp/code/github/openclaw/src/agents/pi-embedded-runner/run.ts

while (true) {
  attemptedThinking.add(thinkLevel);

  const attempt = await runEmbeddedAttempt({...});

  // Handle context overflow - auto-compact and retry
  if (contextOverflowError && overflowCompactionAttempts < MAX_ATTEMPTS) {
    overflowCompactionAttempts++;
    const compactResult = await compactEmbeddedPiSessionDirect({...});
    if (compactResult.compacted) {
      continue; // Retry after compaction
    }
  }

  // Handle auth profile rotation - try next account
  if (shouldRotate && await advanceAuthProfile()) {
    continue; // Retry with new auth
  }

  // Handle thinking level fallback
  const fallbackThinking = pickFallbackThinkingLevel({...});
  if (fallbackThinking) {
    thinkLevel = fallbackThinking;
    continue; // Retry with different thinking level
  }

  // Success or unrecoverable error
  return {...};
}

Loop Termination Logic

  1. Success: Agent completes (stop_reason = "end_turn")
  2. Error escalation: After retry budget exhausted, throw FailoverError
  3. Timeout: timeoutMs kills the run
  4. Abort signal: Caller can abort via AbortSignal

Self-Correction Mechanisms

  • Context overflow: Auto-compact session history (up to 3 attempts)
  • Tool result truncation: Truncate oversized tool outputs
  • Auth rotation: Rotate to next API key on rate limits
  • Thinking level fallback: Try lower thinking levels if unsupported

Multi-Turn Agent Steps

File: /Users/ajsharp/code/github/openclaw/src/agents/tools/agent-step.ts

export async function runAgentStep(params: {
  sessionKey: string;
  message: string;
  extraSystemPrompt: string;
  timeoutMs: number;
}): Promise<string | undefined> {
  // Submit message
  const response = await callGateway({ method: "agent", params: {...} });

  // Wait for completion
  const wait = await callGateway({
    method: "agent.wait",
    params: { runId, timeoutMs: stepWaitMs }
  });

  // Fetch result
  return await readLatestAssistantReply({ sessionKey });
}

Pattern: Allows multi-turn agent loops where each step builds on the previous.


6. Multi-Agent Pipeline Orchestration

Cron Tool for Scheduled Work

File: /Users/ajsharp/code/github/openclaw/src/agents/tools/cron-tool.ts

// Schedule types
{ "kind": "at", "at": "<ISO-8601 timestamp>" }  // One-shot
{ "kind": "every", "everyMs": <ms> }             // Recurring
{ "kind": "cron", "expr": "<cron-expr>" }        // Cron expression

// Payload types
{ "kind": "systemEvent", "text": "<message>" }   // Inject system event
{ "kind": "agentTurn", "message": "<prompt>" }   // Run agent with message

// Delivery modes
{ "mode": "announce", "channel": "...", "to": "..." }  // Deliver result

Skills as Workflow Templates

File: /Users/ajsharp/code/github/openclaw/.agents/skills/PR_WORKFLOW.md

1. `review-pr` — review only, produce findings
2. `prepare-pr` — rebase, fix, gate, push to PR head branch
3. `merge-pr` — squash-merge, verify MERGED state, clean up

Skills execute workflow, maintainers provide judgment.
Always pause between skills to evaluate technical direction.

System Prompt Integration:

Before replying: scan <available_skills>.
If exactly one skill clearly applies: read its SKILL.md, then follow it.

Example: Coding Agent Workflow

File: /Users/ajsharp/code/github/openclaw/skills/coding-agent/SKILL.md

# 1. Spawn Codex in background
bash pty:true workdir:~/project background:true \
  command:"codex --yolo 'Build feature X. When done, run:
  openclaw system event --text \"Done: Feature X\" --mode now'"

# 2. Agent works autonomously
# 3. On completion, triggers wake event
# 4. Main agent resumes and sees result

Handoff Mechanisms

  1. Cron job: Schedule next step
  2. Sub-agent spawn: Delegate to specialist
  3. System event: Inject task into session
  4. Delivery config: Route result to specific channel/user

Key Patterns for ConductorBot

1. Prompt Engineering is Primary ✅ HIGH PRIORITY

What OpenClaw does:

  • System prompt explicitly says "do not narrate routine, low-risk tool calls"
  • Encourages sub-agent delegation for complex work
  • Uses heartbeat prompts to check for pending work

For ConductorBot:

  • Shape agent behavior through system prompts rather than question intercept logic
  • Add role-specific prompts (PM, EM, Coder, QA) that guide autonomous behavior
  • Include "when to escalate" guidelines in prompts

Implementation:

// claude-conductor/src/roles/pm-agent.yaml
systemPrompt: |
  You are a Product Manager agent.

  ## Autonomy Guidelines
  - DO NOT ask for clarification on standard PM tasks (writing specs, user stories)
  - DO ask when technical feasibility is unclear
  - DO ask when user preferences matter (UX decisions, priorities)
  - Keep specs concise and actionable

  ## Tool Usage
  - Call linear.createComment() without narration
  - Use supervisor.escalate() only for critical decisions

2. Heartbeat Loop Pattern ✅ HIGH PRIORITY

What OpenClaw does:

// Every 30min:
1. Send heartbeat prompt to agent
2. If agent responds "HEARTBEAT_OK"  discard, no user notification
3. If agent has content  deliver to user
4. Check HEARTBEAT.md for pending tasks

For ConductorBot:

  • Implement periodic polling with task queue
  • Use Linear issue status changes as triggers
  • Add HEARTBEAT.md pattern to workspace

Implementation:

// claude-conductor/src/daemon/heartbeat-poller.ts
export class HeartbeatPoller {
  async poll() {
    const tasks = await this.loadTaskQueue(); // From HEARTBEAT.md

    for (const task of tasks) {
      const result = await this.workflowEngine.execute({
        workflow: task.workflow,
        input: task.description,
      });

      if (result.status === "HEARTBEAT_OK") {
        // Silent completion, no notification
        continue;
      }

      // Deliver result to Linear/Slack
      await this.commsAdapter.notify(result);
    }
  }
}

3. Sub-Agent Spawn for Pipeline Autonomy ⚠️ MEDIUM PRIORITY

What OpenClaw does:

Main Agent:
  - Delegates work via sessions_spawn(task, label, model, timeout)
  - Continues other work
  - Receives announcement when sub-agent completes

Sub-agent:
  - Isolated session with focused task
  - Works autonomously
  - Announces result back to parent
  - Optionally auto-deleted after completion

For ConductorBot:

  • Use for PM→EM→Coder→QA pipeline
  • Each agent is a "sub-workflow" that announces completion
  • Parent workflow waits for all sub-agents before proceeding

Decision: This maps well to ConductorBot's workflow engine. Instead of spawning sub-agents, use nested workflows with parallel execution.

4. Silent Tokens and Heartbeat Acks ✅ HIGH PRIORITY

What OpenClaw does:

// Agent can signal "nothing to say" without user notification
if (reply === "HEARTBEAT_OK" || reply === SILENT_REPLY_TOKEN) {
  // Don't deliver to user
}

For ConductorBot:

  • Add HEARTBEAT_OK token to agent responses
  • Supervisor checks for token before escalating to comms adapters
  • Reduces noise in Linear comments and Slack channels

Implementation:

// claude-conductor/src/core/supervisor.ts
const SILENT_TOKENS = ["HEARTBEAT_OK", "SILENT_REPLY", "NO_ACTION_NEEDED"];

async intercept(toolCall: AskUserQuestionCall) {
  const response = await this.aiProvider.complete({
    prompt: `Should we escalate this question or can you answer it?

    Question: ${toolCall.question}

    If you can answer, provide answer.
    If no action needed, respond with: HEARTBEAT_OK`,
  });

  if (SILENT_TOKENS.some(token => response.includes(token))) {
    return { escalate: false, silentCompletion: true };
  }

  // ... continue with confidence check
}

5. Skills as Workflow Templates ✅ MEDIUM PRIORITY

What OpenClaw does:

  • SKILL.md files provide step-by-step instructions
  • Agent reads relevant skill before starting work
  • Skills encode best practices

For ConductorBot:

  • Create SKILL.md files for each agent role
  • Store in claude-conductor/skills/ directory
  • Include in role config

Implementation:

# claude-conductor/roles/pm-agent.yaml
role: pm-agent
skillFile: skills/pm-agent/SKILL.md
systemPrompt: |
  Read ${skillFile} before starting work.
  Follow the PM workflow template exactly.
# skills/pm-agent/SKILL.md

## PM Agent Workflow

### Phase 1: Spec Writing
1. Read Linear issue description
2. Write detailed spec with:
   - User stories
   - Acceptance criteria
   - Technical considerations
3. Post spec as Linear comment

### Phase 2: Clarifications
1. If spec is complete → respond with "HEARTBEAT_OK"
2. If you need technical input → escalate to EM agent
3. If you need user preference → escalate to human

### Phase 3: Handoff
1. Label issue "spec-complete"
2. Assign to EM agent
3. Respond with "HEARTBEAT_OK"

6. Cron for Scheduled Polling ✅ HIGH PRIORITY

What OpenClaw does:

// Schedule agent run
cron.add({
  schedule: { kind: "cron", expr: "0 9 * * *" },
  payload: { kind: "agentTurn", message: "Daily standup" },
  delivery: { mode: "announce", channel: "slack", to: "#team" }
});

For ConductorBot:

  • Already implemented in daemon.ts!
  • Use for polling Linear/GitHub triggers
  • Add heartbeat polling to existing poll loop

Enhancement:

// claude-conductor/src/daemon/daemon.ts
async poll() {
  // Existing: poll Linear for trigger events
  const triggerEvents = await this.linearAdapter.pollTriggers();

  // NEW: poll for heartbeat tasks
  const heartbeatTasks = await this.loadHeartbeatTasks();

  for (const task of [...triggerEvents, ...heartbeatTasks]) {
    await this.workflowEngine.execute({
      workflow: task.workflow,
      input: task.description,
    });
  }
}

Architecture Comparison

OpenClaw Approach

┌─────────────────┐
│  Main Agent     │
│  (in session)   │
└────────┬────────┘
         │
         ├─ Heartbeat poll (every 30min)
         │  └─ HEARTBEAT.md task queue
         │
         ├─ Sub-agent spawn
         │  ├─ Sub-agent 1 (isolated session)
         │  ├─ Sub-agent 2 (isolated session)
         │  └─ Announcements back to main
         │
         └─ Cron jobs
            └─ Scheduled agent turns

Key: Peer-to-peer coordination, no central orchestrator.

ConductorBot Approach (Current)

┌─────────────────┐
│  Daemon         │
│  (polls Linear) │
└────────┬────────┘
         │
         ├─ WorkflowEngine
         │  ├─ Step 1 (sequential)
         │  ├─ Step 2 (sequential)
         │  └─ Step 3 (sequential)
         │
         └─ Supervisor
            └─ Intercepts AskUserQuestion
               └─ Escalates to comms adapter

Key: Centralized orchestrator with sequential steps.

ConductorBot Approach (Enhanced with OpenClaw Patterns)

┌─────────────────┐
│  Daemon         │
│  + Heartbeat    │
│  Poller         │
└────────┬────────┘
         │
         ├─ Poll Linear triggers
         ├─ Poll HEARTBEAT.md tasks
         │
         └─ WorkflowEngine
            ├─ Parallel steps (PM + EM)
            │  ├─ Sub-workflow 1
            │  └─ Sub-workflow 2
            │
            ├─ Sequential steps (Coder → QA)
            │
            └─ Supervisor
               ├─ Check HEARTBEAT_OK token
               ├─ Answer with AI if confident
               └─ Escalate to human if needed

Key: Hybrid approach - centralized orchestration with heartbeat polling and parallel execution.


Recommended Implementation Plan

Phase 1: Heartbeat & Silent Tokens (2 days)

Goal: Reduce noise, enable autonomous loops

  1. Add silent token detection to Supervisor

    // src/core/supervisor.ts
    const SILENT_TOKENS = ["HEARTBEAT_OK", "SILENT_REPLY"];
    
    if (SILENT_TOKENS.some(token => response.includes(token))) {
      return { escalate: false, silentCompletion: true };
    }
  2. Add heartbeat poller to Daemon

    // src/daemon/heartbeat-poller.ts
    export class HeartbeatPoller {
      async poll() {
        const tasks = await this.loadTaskQueue(); // HEARTBEAT.md
        for (const task of tasks) {
          await this.workflowEngine.execute(task);
        }
      }
    }
  3. Create HEARTBEAT.md task queue format

    # HEARTBEAT.md
    
    ## Pending Tasks
    - [ ] workflow: pm-review, input: "Review Linear issue XYZ-123"
    - [ ] workflow: qa-test, input: "Test PR #456"

Phase 2: Role-Specific Prompts (2 days)

Goal: Guide agents to work autonomously

  1. Add systemPrompt to role configs

    # roles/pm-agent.yaml
    systemPrompt: |
      You are a PM agent.
      DO NOT ask for clarification on standard PM tasks.
      DO ask when technical feasibility is unclear.
      Use HEARTBEAT_OK when no action needed.
  2. Create skills directory

    claude-conductor/skills/
    ├── pm-agent/SKILL.md
    ├── em-agent/SKILL.md
    ├── coder-agent/SKILL.md
    └── qa-agent/SKILL.md
    
  3. Update ClaudeSdkProvider to inject system prompt

    // src/providers/claude-sdk-provider.ts
    const systemPrompt = [
      role.systemPrompt,
      role.skillFile ? await readFile(role.skillFile) : "",
    ].join("\n\n");

Phase 3: Parallel Workflow Steps (3 days)

Goal: Enable concurrent agent work

  1. Add parallel mode to workflow schema

    steps:
      - id: review
        mode: parallel
        substeps:
          - id: pm-review
            agent: pm-agent
          - id: tech-review
            agent: em-agent
  2. Update WorkflowEngine to handle parallel steps

    // src/core/workflow-engine.ts
    if (step.mode === "parallel") {
      const results = await Promise.all(
        step.substeps.map(substep => this.executeStep(substep))
      );
      return this.aggregateResults(results);
    }

Phase 4: Retry & Auto-Compaction (From Previous Research)

See openclaw-architecture-analysis.md for retry infrastructure plan.


Files to Reference

OpenClaw (for implementation patterns)

System Prompts:

  • ~/code/github/openclaw/src/agents/system-prompt.ts (main prompt builder, ~650 lines)
  • ~/code/github/openclaw/src/agents/pi-embedded-runner/system-prompt.ts (embedded runner)
  • ~/code/github/openclaw/src/agents/subagent-announce.ts (sub-agent prompt)

Agent Loop:

  • ~/code/github/openclaw/src/agents/pi-embedded-runner/run.ts (main retry loop)
  • ~/code/github/openclaw/src/agents/cli-runner.ts (CLI agent runner)
  • ~/code/github/openclaw/src/agents/tools/agent-step.ts (multi-turn loops)

Autonomy Tools:

  • ~/code/github/openclaw/src/agents/tools/sessions-spawn-tool.ts (sub-agent spawning)
  • ~/code/github/openclaw/src/agents/tools/cron-tool.ts (scheduled tasks)

Heartbeat System:

  • ~/code/github/openclaw/src/auto-reply/heartbeat.ts (heartbeat prompts and token stripping)
  • ~/code/github/openclaw/src/auto-reply/tokens.ts (SILENT_REPLY_TOKEN, HEARTBEAT_TOKEN)

Workflows:

  • ~/code/github/openclaw/.agents/skills/PR_WORKFLOW.md (multi-step PR workflow)
  • ~/code/github/openclaw/skills/coding-agent/SKILL.md (Codex/Claude Code orchestration)
  • ~/code/github/openclaw/skills/github/SKILL.md (GitHub operations)

ConductorBot (to modify)

Core:

  • claude-conductor/src/core/supervisor.ts (add silent token detection)
  • claude-conductor/src/core/workflow-engine.ts (add parallel execution)
  • claude-conductor/src/daemon/daemon.ts (add heartbeat polling)

Providers:

  • claude-conductor/src/providers/claude-sdk-provider.ts (inject system prompts)

New Files:

  • claude-conductor/src/daemon/heartbeat-poller.ts (heartbeat task queue)
  • claude-conductor/skills/**/*.md (workflow templates)

Summary

OpenClaw achieves autonomous agent operation through:

  1. Prompt engineering → "Just do it, don't ask"
  2. Heartbeat polling → Check for work every 30min, silent acks
  3. Sub-agent delegation → Isolate complex work
  4. Skills as templates → Encode best practices
  5. Auto-retry loops → Self-heal errors
  6. Cron scheduling → Trigger work at intervals

No central supervisor needed - agents coordinate via sessions and delivery config, with heartbeat polls providing the "keep working" signal.

For ConductorBot: Adopt heartbeat polling, silent tokens, role-specific prompts, and parallel workflows. Skip sub-agent spawning (use nested workflows instead).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment