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
- Download agent-loop-mcp.zip — installable skill directory
- Download SKILL.md — raw skill file
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.mdor.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_FOUNDnamingloop_workspace_registerorloop_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_nameoragent_nameon 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; useloop_agent_inspector the pair-scoped resource. - NEVER rely on
AGENT_LOOP_DEV_AGENT_ID/AGENT_LOOP_DEV_WORKSPACE_ID— removed. - NEVER use
loop_run_failfor ordinary CYCLE_COMPLETE. - NEVER forget
fencing_tokenon heartbeat/complete/publish/read calls.