Install the full agent-loop-mcp skill

This page hosts the complete OpenCode / HOS skill for AgentLoopMCP (pair identity: workspace_name + agent_name). Downloads are public — no login.

Downloads

Install paths

  • OpenCode / Grok: ~/.config/opencode/skills/agent-loop-mcp/SKILL.md
  • HOS bundle: temporal-hos/docker/opencode-bundle/skills/agent-loop-mcp/SKILL.md
  • Project: .opencode/skills/agent-loop-mcp/SKILL.md or .agents/skills/agent-loop-mcp/SKILL.md

Full skill content

Below is the full skill body (same bytes as the download).


Agent Loop MCP — HOS Agent Lifecycle Skill

What this is

AgentLoopMCP is the transactional loop-state and coordination service for recurring

HOS agents. It replaces file-based daily logs as the authoritative persistence layer

for agent continuity. Every HOS agent cycle MUST be wrapped in a loop run.

Identity (DEV-28 shipped — pair model)

Identity is caller-declared. There is no process-wide AGENT_LOOP_DEV_* and

no loop_self_inspect tool.

Every agent-scoped call requires both:

Field Rule
workspace_name Globally unique company workspace (HOS uses chrilan)
agent_name Unique within that workspace (this agent's registered name)

One-time registration (before first cycle on a fresh DB)


agent-loop_loop_workspace_register(payload={
  "workspace_name": "chrilan",
  "company_name": "Chrilan"
})

agent-loop_loop_agent_register(payload={
  "workspace_name": "chrilan",
  "agent_name": "<this-agent-name>"   // e.g. "hos-whatsapp-overview"
})
  • Unknown pair → NOT_FOUND naming loop_workspace_register or loop_agent_register.
  • Metadata conflict on re-register → REGISTRY_CONFLICT (409).
  • Wrong-pair run ownership → FORBIDDEN (no owner disclosure).

Inspect

Tool (pair-scoped continuity metadata):


agent-loop_loop_agent_inspect(payload={
  "workspace_name": "chrilan",
  "agent_name": "<this-agent-name>"
})

Resource URI:


agent-loop://workspaces/{workspace_name}/agents/{agent_name}

The mandatory lifecycle (every cycle, no exceptions)


E1 step → agent-loop_loop_run_start(payload={workspace_name, agent_name, schedule_key, trigger_id})
  ↓ get run_id + fencing_token from response
  ... domain work ...
  ↓ optionally: loop_shared_publish_now / loop_shared_read_more (same pair + run_id + fencing_token)
last step → agent-loop_loop_run_complete(payload={workspace_name, agent_name, run_id, fencing_token, completion_id, result_summary, private_state})

CRITICAL: all tools take a payload object

Every tool wraps its arguments inside a single payload parameter.

You MUST pass {payload: {...}} not the fields directly.

Tool reference (exact signatures)

loop_run_start

Called at the first domain step (E1), after identity/capability check.


agent-loop_loop_run_start(payload={
  "workspace_name": "chrilan",
  "agent_name": "<this-agent-name>",
  "schedule_key": "<agent-name>:<cadence>",     // e.g. "hos-whatsapp-overview:5min"
  "trigger_id": "<unique-id>",                   // e.g. "manual-2026-08-12T10:00:00Z"
  "triggered_at": null,                          // optional ISO datetime
  "requested_lease_seconds": 300,                // default 300
  "max_shared_notes": 100                         // default 100
})

Returns: run_id, fencing_token, status, server_now, lease_expires_at,

previous_successful_run, private_state, shared_inbox, recovery.

SAVE run_id and fencing_token — every subsequent call needs them.

loop_run_heartbeat


agent-loop_loop_run_heartbeat(payload={
  "workspace_name": "chrilan",
  "agent_name": "<this-agent-name>",
  "run_id": "<from start>",
  "fencing_token": <int from start>,
  "extend_seconds": 300
})

loop_run_complete


agent-loop_loop_run_complete(payload={
  "workspace_name": "chrilan",
  "agent_name": "<this-agent-name>",
  "run_id": "<from start>",
  "fencing_token": <int from start>,
  "completion_id": "<unique-id>",
  "result_summary": "One-line human-readable summary",
  "private_state": {
    "objective": "What this agent does",
    "summary_for_next_run": "What the next cycle needs to know",
    "unresolved_items": [],
    "decisions": [],
    "known_facts": [],
    "next_run_actions": [],
    "suppressed_items": []
  },
  "metrics": {
    "source_items_read": 0,
    "source_items_processed": 0,
    "business_actions_attempted": 0,
    "business_actions_succeeded": 0
  }
})

private_state.objective and private_state.summary_for_next_run are required (min_length=1).

loop_run_fail


agent-loop_loop_run_fail(payload={
  "workspace_name": "chrilan",
  "agent_name": "<this-agent-name>",
  "run_id": "<from start>",
  "fencing_token": <int from start>,
  "failure_id": "<unique-id>",
  "category": "AGENT_EXECUTION_ERROR",
  "summary": "What went wrong"
})

loop_shared_publish_now


agent-loop_loop_shared_publish_now(payload={
  "workspace_name": "chrilan",
  "agent_name": "<this-agent-name>",
  "run_id": "<from start>",
  "fencing_token": <int from start>,
  "dedupe_key": "<unique-key>",
  "note": {
    "kind": "status",
    "priority": "normal",
    "subject": "Short subject line",
    "summary": "What happened and what's needed",
    "audience": {
      "type": "channel",
      "channel_key": "hos-communications"
    },
    "requires_ack": true
  }
})

Audience may also target agents by name (agent_names: ["hos-tickets-overview"]), not internal keys.

loop_shared_read_more


agent-loop_loop_shared_read_more(payload={
  "workspace_name": "chrilan",
  "agent_name": "<this-agent-name>",
  "run_id": "<from start>",
  "fencing_token": <int from start>,
  "limit": 50,
  "after_delivery_id": null
})

loop_agent_inspect


agent-loop_loop_agent_inspect(payload={
  "workspace_name": "chrilan",
  "agent_name": "<this-agent-name>"
})

Registration tools


agent-loop_loop_workspace_register(payload={"workspace_name": "chrilan", "company_name": "Chrilan"})
agent-loop_loop_agent_register(payload={"workspace_name": "chrilan", "agent_name": "<name>"})

Complete cycle example (copy-paste pattern)


# Once per environment (idempotent if metadata matches)
agent-loop_loop_workspace_register(payload={"workspace_name": "chrilan", "company_name": "Chrilan"})
agent-loop_loop_agent_register(payload={"workspace_name": "chrilan", "agent_name": "hos-whatsapp-overview"})

# E1: Start the run
start = agent-loop_loop_run_start(payload={
  "workspace_name": "chrilan",
  "agent_name": "hos-whatsapp-overview",
  "schedule_key": "hos-whatsapp-overview:5min",
  "trigger_id": "manual-2026-08-12T10:00:00Z"
})
run_id = start.run_id
fencing_token = start.fencing_token

# ... domain work; use start.private_state and start.shared_inbox ...

agent-loop_loop_shared_publish_now(payload={
  "workspace_name": "chrilan",
  "agent_name": "hos-whatsapp-overview",
  "run_id": run_id,
  "fencing_token": fencing_token,
  "dedupe_key": "cycle-2026-08-12-10-comms",
  "note": {
    "kind": "status",
    "subject": "WhatsApp overview cycle complete",
    "summary": "30 inbound conversations processed, 0 P1",
    "audience": {"type": "channel", "channel_key": "hos-communications"}
  }
})

agent-loop_loop_run_complete(payload={
  "workspace_name": "chrilan",
  "agent_name": "hos-whatsapp-overview",
  "run_id": run_id,
  "fencing_token": fencing_token,
  "completion_id": "complete-2026-08-12T10:05:00Z",
  "result_summary": "Cycle complete: 1081 chats, 30 inbound, 0 P1",
  "private_state": {
    "objective": "Monitor Chrilan Support WhatsApp line every 5 minutes",
    "summary_for_next_run": "Watermark at 2026-08-12T10:00Z. 12 ticket-worthy conversations. No P1.",
    "unresolved_items": [
      {"key": "compliance-login-260977486690", "description": "Customer login failure handoff from Compliance", "status": "open", "priority": "high"}
    ]
  }
})

Integration with existing patterns

  • task_note remains for in-task audit during the current run
  • memory_remember remains for long-term semantic memory
  • loop_run_complete.private_state is the authoritative cycle-to-cycle handoff
  • loop_shared_publish_now replaces the communication radar file
  • File-based private_state is not required

Anti-patterns (banned)

  • NEVER skip loop_run_start. A cycle without a run has no persistence.
  • NEVER skip loop_run_complete. An incomplete run holds a lease.
  • NEVER omit workspace_name or agent_name on any agent-scoped call.
  • NEVER use another agent's agent_name (cross-agent spoofing is a guardrail violation).
  • NEVER pass fields directly — always wrap in payload: {...}.
  • NEVER call loop_self_inspect — it does not exist; use loop_agent_inspect or the pair-scoped resource.
  • NEVER rely on AGENT_LOOP_DEV_AGENT_ID / AGENT_LOOP_DEV_WORKSPACE_ID — removed.
  • NEVER use loop_run_fail for ordinary CYCLE_COMPLETE.
  • NEVER forget fencing_token on heartbeat/complete/publish/read calls.

Next Steps