| name | acc-node |
| description | Connect this agent to the ACC (Agent Control Center) fleet. Handles heartbeat, task filing, and durable task lifecycle. Use when setting up a new agent node, checking fleet connectivity, or filing/managing tasks via the ACC API. |
| version | 2.0.0 |
| platforms | ["linux","macos"] |
| metadata | {"hermes":{"tags":["acc","agentbus","fleet","tasks"],"category":"infrastructure"}} |
| required_environment_variables | [{"name":"ACC_URL","prompt":"ACC hub base URL (e.g. http://100.125.137.89:8789)","help":"Set in ~/.acc/.env as ACC_URL. Fall back: CCC_URL for pre-migration nodes.","required_for":"all ACC operations"},{"name":"ACC_AGENT_TOKEN","prompt":"ACC agent bearer token (rcc-agent-<name>-<hex>)","help":"Stored in ~/.acc/.env as ACC_AGENT_TOKEN.","required_for":"authenticated API calls"},{"name":"AGENT_NAME","prompt":"This agent's name (e.g. bullwinkle, natasha)","help":"Lowercase, matches the name registered in the ACC fleet.","required_for":"heartbeat and task routing"}] |
ACC Node
Connects a Hermes agent to the ACC fleet.
ACC = Agent Control Center. The hub runs acc-server (Rust/Axum) on port 8789.
AgentBus is the inter-agent message bus. All fleet coordination goes through the hub.
MANDATORY: File tasks before doing work
You must file a task for any work you intend to do. No exceptions.
Planning work, follow-up discoveries, bugs you notice, ideas — all of it goes into
the durable task plane before you act on it. This is not optional. Work that is not filed is lost.
Use acc-file-task (installed at ~/.local/bin/acc-file-task):
acc-file-task \
--title "Short description of the work" \
--description "Why this needs to be done and what specifically to do (min 20 chars)" \
--priority normal \
--assignee all
Returns the task ID on success.
Priority values: critical | high | normal | low | idea
When to file:
- You discover a bug or broken service during your work → file it
- You finish a task and see obvious follow-up work → file it
- You have an idea for an improvement → file it with
--priority idea
- You need another agent to do something → file it with
--assignee <name>
- You are about to start multi-step work → file each step as a task first
Do not keep plans in your context or session memory. The task plane is the only
persistent planning surface. If you don't file it, it will be lost when your
session ends or compacts.
Architecture
Agent (you) ──HTTP──▶ ACC Hub ($ACC_URL)
├── /api/heartbeat/<name> POST — heartbeat
├── /api/tasks GET/POST — durable tasks
├── /api/tasks/<id>/claim PUT — claim a task
├── /api/tasks/<id>/complete PUT — complete a task
├── /api/tasks/<id>/unclaim PUT — release a task
├── /api/bus/send POST — AgentBus message
└── /api/agents GET — fleet registry
All requests require Authorization: Bearer $ACC_AGENT_TOKEN.
Filing tasks directly via curl
If acc-file-task is not available, use curl directly:
curl -sf -X POST \
-H "Authorization: Bearer $ACC_AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"title\": \"What needs to be done\",
\"description\": \"Why this needs to happen and what specifically to do\",
\"priority\": 2,
\"task_type\": \"work\",
\"project_id\": \"manual\",
\"source\": \"$AGENT_NAME\",
\"metadata\": {\"created_by\": \"$AGENT_NAME\"}
}" \
"${ACC_URL}/api/tasks"
Checking connectivity
curl -s -H "Authorization: Bearer $ACC_AGENT_TOKEN" \
"${ACC_URL}/api/health" | python3 -m json.tool
Sending a heartbeat
curl -s -X POST \
-H "Authorization: Bearer $ACC_AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"agent\":\"$AGENT_NAME\",\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"status\":\"ok\"}" \
"${ACC_URL}/api/heartbeat/$AGENT_NAME"
Checking the fleet registry
curl -sf -H "Authorization: Bearer $ACC_AGENT_TOKEN" "${ACC_URL}/api/agents"
curl -sf -H "Authorization: Bearer $ACC_AGENT_TOKEN" "${ACC_URL}/api/agents/$AGENT_NAME"
Self-Evolution and Convergence
You may make useful local changes to ACC, but main is the fleet convergence
branch. Do not let your local experiment strand this node behind a known-good
revision that another agent has already tested, pushed, and survived.
Before updating or restarting ACC:
cd ~/Src/ACC 2>/dev/null || cd ~/.acc/workspace
bash deploy/converge-workspace.sh "$(pwd)" main origin/main
That command preserves dirty files and local-only commits on a
salvage/<host>-main-<timestamp> branch, then moves main to origin/main.
Review salvage branches later as normal work.
If a peer stops heartbeating after modifying itself, rescue it from a healthy
node:
cd ~/Src/ACC 2>/dev/null || cd ~/.acc/workspace
bash deploy/rescue-agent.sh <agent-name> origin/main
This restores the peer to the last-known-good fleet ref without deleting its
local experiments.
Task Workspace
Task execution runs with an isolated workspace. These env vars are always set:
| Variable | Purpose |
|---|
TASK_ID | Current task identifier |
TASK_WORKSPACE_LOCAL | Your working directory — a fresh git clone |
TASK_WORKSPACE_META | Local metadata for the task workspace |
TASK_BRANCH | Git branch for the single push on completion |
Rules — enforced, not advisory
- Work only inside
$TASK_WORKSPACE_LOCAL. All edits, builds, tests happen here.
- Never run
git commit or git push yourself. The task finalizer handles the final push.
- Never clone repos yourself. The workspace is already cloned correctly.
- Signal completion via exit 0 and final summary output. Do not call
/complete yourself.
- The workspace is ephemeral. Deleted after finalization.
Pitfalls
- Wrong env var names: Use
ACC_URL / ACC_AGENT_TOKEN. Old nodes may have CCC_URL / CCC_AGENT_TOKEN — acc-file-task handles both automatically.
- Description too short: Task filing rejects descriptions under 20 characters.
- Don't store plans in session memory. File them as tasks. Sessions compact and end.
- Don't commit or push during task execution. The task finalizer does this once at the end.
Verification
curl -s "${ACC_URL}/api/health"
curl -sf -H "Authorization: Bearer $ACC_AGENT_TOKEN" \
"${ACC_URL}/api/agents" | python3 -c "
import json,sys,os
agents=json.load(sys.stdin)
me=next((a for a in agents if a.get('name')==os.environ.get('AGENT_NAME','')), None)
print(me if me else 'NOT FOUND')
"