Agent Workflow
The standard agent loop, multi-agent coordination, and hosted plans
Every agent — human-operated, LLM-driven, or automated — interacts with hence through the same set of CLI commands. The workflow is intentionally simple: read the plan, find your tasks, claim them, do the work, assert what you learned, and mark them done. The hence reasoner handles all the logic about what is ready, who should work on what, and what the current state of the project is.
This guide walks through the full lifecycle, from setting your identity to coordinating across multiple machines with hence.run hosted plans.
hence installed and a plan file named plan.spl
in your current directory. See Getting Started to create your
first plan, or Writing Plans to understand the plan format.
The Standard Agent Loop
Every agent session follows the same repeating cycle. Whether you are an LLM processing tasks autonomously or a human checking in on a project, these are the steps:
-
Establish your identity — run
hence agent whoamito confirm which agent identity is active. This prints your agent name and, if you have a cryptographic keypair, your public key. It is a fast sanity check before you start claiming tasks.$ hence agent whoami supervisor:ed25519:xfRAzZFG agent:ed25519:xfRAzZFG evaluator:ed25519:3jB3fzQT PeerId: 12D3KooWP96WBe... -
Read plan metadata — run
hence plan info plan.splto see high-level information about the plan: its title, description, declared agents, and the total number of tasks.$ hence plan info plan.spl Plan: Title: Backend Refactor Sprint Status: active Created: 2026-02-24 -
View the full task board — run
hence plan board plan.splto see all tasks and their current status across every kanban column. This gives you the complete picture before narrowing down to your own work.$ hence plan board plan.spl +--------------+--------------+--------------+--------------+--------------+ | BACKLOG | READY | IN PROGRESS | BLOCKED | DONE | +--------------+--------------+--------------+--------------+--------------+ |loadtest |write-tests ..|api @alice |deploy |setup | |tests |update-docs ..|api-review @b.| |add-ci | +--------------+--------------+--------------+--------------+--------------+ Tasks: 2 backlog, 2 ready, 2 in-progress, 1 blocked, 2 done -
Find your assigned tasks — run
hence task next plan.splto see which tasks the plan's rules assign to you specifically. This filters the READY column to only show tasks where the derived factassign-to-TASK-AGENTmatches your identity. The output includes ready-to-paste claim commands.$ hence task next plan.spl Next actions for alice: 1. write-tests @alice — hence task claim write-tests plan.spl --agent alice 2. update-docs @alice — hence task claim update-docs plan.spl --agent alice -
Claim a task — run
hence task claim TASK plan.splto take ownership of a task. This appends a(claims ...)block to the plan file and moves the task to IN PROGRESS on the board.$ hence task claim write-tests plan.spl Added: (claims agent:alice :at "2026-02-24T09:00:00Z" ...) (given claim-v1-write-tests) ... Next actions for alice: (no actions available) - Do the work — execute whatever the task requires: write code, run a command, call an API, review a document. hence does not prescribe what "the work" looks like — it only tracks the task lifecycle around it.
-
Assert findings — as you work, use
hence task assertto record facts or rules that other agents and the plan's logic can build on. This is how agents communicate discoveries to each other without out-of-band channels.$ hence task assert '(given tests-passing)' plan.spl $ hence task assert '(given coverage-above-80)' plan.spl --task write-tests -
Complete the task — run
hence task complete TASK plan.splto mark the task done. This appends a(completed ...)block to the plan, moves the task to DONE, and may unlock downstream tasks that were waiting on this one.$ hence task complete write-tests plan.spl Added: (claims agent:alice :at "2026-02-24T10:42:17Z" (given completed-write-tests)) -
Back to step 4 — run
hence task next plan.splagain to find your next assignment. Newly unlocked tasks will now appear in the list.
hence task next --json plan.spl,
parse the output, claim and process each task, then loop. The --json flag on most commands
produces machine-readable output suitable for programmatic handling.
The HENCE_AGENT Environment Variable
All hence commands that act on behalf of an agent — claiming, completing, asserting — need to know
which agent is performing the action. The cleanest way to provide this is via the
HENCE_AGENT environment variable, set once at the top of your session.
# Set once for the session — all commands inherit it
export HENCE_AGENT=alice
# Now claim, complete, and assert all tag actions as "alice"
hence task claim refactor-auth plan.spl
hence task assert '(given auth-refactor-done)' plan.spl
hence task complete refactor-auth plan.spl
If you need to override the environment variable for a single command, use the --agent
flag:
# Override for a single command
hence task claim deploy-staging plan.spl --agent devops-bot
Why agent identity matters
Agent identity is how the plan's assignment logic targets the right agents. When a plan rule says:
normally assign-to-write-tests-alice
given task-write-tests
given agent-alice
The reasoner fires this rule when agent-alice is a known fact. That fact comes from
the HENCE_AGENT value you export. Without it, hence task next would not
know which assignments to show you.
Agent identity also appears in the audit trail recorded in the plan file. Every (claims ...),
(completed ...), and (asserted-by ...) block references the agent name
so the board can accurately show who has claimed what.
Agent name formats
| Format | Example | When to use |
|---|---|---|
| Simple name | alice |
Informal projects, trusted local environments |
| Role name | coder, reviewer, devops |
Role-based assignment rather than person-specific |
| Model name | claude, codex, gemini |
LLM agents acting as first-class participants |
| Qualified key | agent:ed25519:AAAA...4rXQ |
Cryptographically verified identity across machines |
agent:PUBKEY) become useful when plans are shared via hence.run and
you want verifiable attribution across untrusted participants.
Understanding hence task next Output
hence task next is your primary entry point into the work queue. It evaluates the
plan's rules against the current set of facts and returns only the tasks that are both READY and
assigned to the active agent.
What "assigned" means
A task is considered assigned to you when the reasoner derives the fact
assign-to-TASK-AGENT — for example, assign-to-write-tests-alice. Plan
authors write rules that produce these conclusions. A typical rule looks like this:
normally assign-to-write-tests-alice
given task-write-tests
given agent-alice
given tests-not-yet-written
The reasoner fires this rule when all three conditions hold. If a more specific rule defeats it — for example, a rule saying a senior reviewer must do the tests first — the assignment may shift. Defeasibility means you always see the current best conclusion, not just static assignment.
Reading the output
$ hence task next plan.spl
Next actions for dev:
1. design @dev — hence task claim design plan.spl --agent dev
Each line includes a copy-pasteable claim command. You can pipe this into your shell or an LLM's tool loop directly.
Machine-readable output
For programmatic use, pass --json to get structured output:
$ hence task next plan.spl --json
{
"agent": "dev",
"next_actions": [
{
"agent": "dev",
"command": "hence task claim design plan.spl --agent dev",
"literal": "assign-to-design-dev",
"task": "design"
}
]
}
hence task next --json plan.spl, pick the first
item from the next_actions array, run its command to claim it, do the
work, and loop." The JSON output makes it trivial to build reliable agentic loops without
brittle text parsing.
Claiming a Task
Claiming signals to other agents and the board that you are actively working on a task. It moves the task from READY to IN PROGRESS and records your agent identity in the plan file.
# Claim a task
hence task claim write-tests plan.spl
# Claim as a specific agent (overrides HENCE_AGENT)
hence task claim write-tests plan.spl --agent alice
What claiming does to the plan file
The plan file is the single source of truth — there is no separate database or server tracking
state. When you claim a task, hence appends a (claims ...) block directly to
plan.spl:
(claims agent:alice
:at "2026-02-24T14:32:00Z"
(given claim-v1-write-tests)
(normally r-cl-state-v1-write-tests claim-v1-write-tests state-claimed-v1-write-tests)
(normally r-cl-chain-v1-write-tests state-claimed-v1-write-tests claimed-write-tests)
)
The reasoner reads this fact on every subsequent evaluation. The derived conclusion
in-progress-write-tests causes the task to appear in the IN PROGRESS column and
suppresses it from hence task next output for other agents.
Releasing a claim
If you claimed a task but cannot finish it — the requirements changed, you are handing it off,
or you simply picked the wrong task — use unclaim to release it back to READY:
# Release the claim, putting the task back to READY
hence task unclaim write-tests plan.spl
Unclaiming appends an (unclaims ...) fact that defeats the earlier (claims ...)
block. The plan file grows but never loses history — you can always see who claimed and unclaimed
tasks over time.
Asserting Facts While Working
Assertions are how agents communicate discoveries, intermediate results, and verdicts to each other — and to downstream plan logic. Instead of Slack messages or external ticket comments, agents write facts directly into the plan file where the reasoner can act on them.
Adding a simple fact
# Assert that a condition is now true
hence task assert '(given tests-passing)' plan.spl
# Tag the assertion with the task you're working on
hence task assert '(given coverage-above-80)' plan.spl --task write-tests
# Multiple facts in one session
hence task assert '(given security-review-approved)' plan.spl
hence task assert '(given no-critical-vulnerabilities)' plan.spl
Each assertion appends a (given ...) fact to the plan file. The reasoner picks it up
immediately on the next evaluation. If a downstream task had a readiness rule waiting on
tests-passing, it will now appear as READY on the board.
Adding a rule
Agents can also assert new rules, not just facts. This is useful when you discover a condition that should change the plan's logic going forward:
# Assert a new defeasible rule
hence task assert '(normally skip-load-testing given staging-unavailable)' plan.spl
# Assert a rule with multiple conditions
hence task assert \
'(normally assign-to-hotfix-devops given task-hotfix given production-incident)' \
plan.spl
Rule assertions let agents dynamically reshape the plan as the project evolves. The plan is not a static document — it is a living knowledge base that agents contribute to.
Common assertion patterns
| Assertion | Typical use |
|---|---|
(given completed-integration-tests) |
Signal that a test suite passed; unlocks downstream tasks |
(given security-review-approved) |
Security agent approves; lets release task become READY |
(given api-schema-finalized) |
Design decision made; unblocks implementation tasks |
(given staging-broken) |
Infrastructure fact; may block deploy-dependent tasks |
(given feature-flag-enabled) |
Ops fact; may change which rollout tasks are needed |
tests-passing over
allTestsAreCurrentlyPassing.
Naming Conventions for Discoveries
Use consistent prefixes so facts are discoverable across agents and easy to reference in downstream rules.
| Prefix | Purpose | Example |
|---|---|---|
discovered- | Findings during execution | discovered-api-deprecated |
decided- | Design decisions made | decided-use-redis |
blocked-by- | Blockers identified | blocked-by-missing-credentials |
requires- | Prerequisites found | requires-api-key |
verified- | Validations passed | verified-authentication-works |
failed- | Failures observed | failed-integration-test |
Blocker/unblocker pattern
Facts (given) cannot be defeated once asserted. To create blockers that can later
be unblocked, use an intermediate derived literal:
; Use intermediate literal that CAN be defeated
(normally r-has-vulnerability discovered-vulnerability has-active-vulnerability)
(except d-block has-active-vulnerability (not ready-deploy))
(except d-unblock verified-fix (not has-active-vulnerability))
This preserves the discovery (discovered-vulnerability) as a permanent audit trail
while allowing its effect on readiness to be defeated when a fix is verified.
Blocking a Task
Sometimes a task cannot proceed due to external factors: a dependency on a third party, a production incident, or an unanswered design question. Rather than leaving it in READY or abandoning the claim, mark it explicitly blocked with a human-readable reason.
# Mark a task as blocked with an explanation
hence task block deploy-staging "waiting on infra team to provision the environment" plan.spl
# Unblock when the impediment is resolved
hence task unblock deploy-staging plan.spl
A blocked task appears in the BLOCKED column of the board with its reason displayed. Other agents
can see at a glance what is impeding progress without having to ask. The reason is stored in the
plan file as a string alongside the (blocked ...) fact.
$ hence plan board plan.spl
+--------------+--------------+--------------+--------------+--------------+
| BACKLOG | READY | IN PROGRESS | BLOCKED | DONE |
+--------------+--------------+--------------+--------------+--------------+
|loadtest | |api @alice |deploy |setup |
|tests | |docs @bob | | |
+--------------+--------------+--------------+--------------+--------------+
Tasks: 2 backlog, 0 ready, 2 in-progress, 1 blocked, 1 done
When you unblock a task, hence appends an (unblocked ...) fact that defeats the
earlier (blocked ...) conclusion. The task returns to whatever status the other rules
conclude — typically READY if all its dependencies are satisfied.
Multi-Agent Coordination
hence is designed from the ground up for multiple agents working on the same plan simultaneously. There is no locking, no contention, and no need to serialize agent actions through a central coordinator. The plan file is append-only: agents only ever add new facts, never modify or delete existing ones.
How concurrent writes are handled
Because the plan file is append-only and facts are monotone (adding a fact never invalidates prior reasoning except through explicit defeat), two agents writing simultaneously produce no logical conflict. Even if a raw file merge produces a file with interleaved lines, the reasoner parses each fact independently and re-derives all conclusions from scratch.
In practice, concurrent appends on a local filesystem are safe — POSIX guarantees atomic writes up to 4096 bytes when appending to a file, and hence claims are designed to stay well under this limit. When using hence.run hosted plans, the remote applies a sequenced log so concurrent writes are ordered without data loss.
Viewing all agent assignments
# See every task's current assignment across all agents
hence task assign plan.spl
Assignments for alice:
+d assign-to-refactor-auth-alice
+d assign-to-write-tests-alice
+d assign-to-update-docs-alice
hence task assign lists all derived assign-to-TASK-AGENT conclusions
currently provable for the active agent. Use hence plan board for the full
multi-agent coordination view including in-progress, blocked, and done states.
Board-level visibility
The board always shows current claim ownership. Agents do not need to communicate out-of-band to know what others are doing — the plan file is the single source of truth, and the board reflects it in real time.
$ hence plan board plan.spl
+--------------+--------------+--------------+--------------+--------------+
| BACKLOG | READY | IN PROGRESS | BLOCKED | DONE |
+--------------+--------------+--------------+--------------+--------------+
|deploy | |api @alice | |setup |
| | |api-review @b.| | |
| | |write-test @c.| | |
+--------------+--------------+--------------+--------------+--------------+
Tasks: 1 backlog, 0 ready, 3 in-progress, 0 blocked, 1 done
Reading the Board
The kanban board produced by hence plan board has five columns. Understanding what
each column means helps you diagnose stuck projects and understand task dependencies at a glance.
| Column | Badge | Meaning |
|---|---|---|
| BACKLOG | backlog | Task is declared in the plan but its readiness rules have not fired yet. Typically this means one or more prerequisite tasks have not completed, or a required fact has not been asserted. No action needed — it will unlock automatically. |
| READY | ready | All readiness conditions are satisfied. The task is available to be claimed. If the plan has assignment rules, it may already be assigned to a specific agent; otherwise any agent can claim it. |
| IN PROGRESS | in progress | An agent has claimed the task and is actively working on it. The claiming agent's name and the claim timestamp are shown. Other agents should not claim the same task unless the original claim is released. |
| BLOCKED | blocked |
An agent explicitly blocked the task with hence task block and provided a
reason. The readiness conditions may be met, but an external impediment prevents progress.
Resolve the impediment and run hence task unblock.
|
| DONE | done |
The task was completed with hence task complete. The completion fact is in
the plan file and may satisfy readiness conditions for downstream tasks, moving them from
BACKLOG to READY automatically.
|
Board view options
The board command supports several output formats for different use cases:
# Default kanban-style view
hence plan board plan.spl
# Dependency tree view — shows parent/child relationships
hence plan board plan.spl --tree
# DAG view — shows full directed acyclic graph of dependencies
hence plan board plan.spl --dag
# Machine-readable JSON
hence plan board plan.spl --json
The --tree flag renders a hierarchy useful for seeing at a glance which tasks unlock which:
$ hence plan board plan.spl --tree
Legend: * done o ready > in-progress x blocked - backlog
project
|-- * setup-repo
| +-- * add-ci
| +-- > @alice refactor-auth
| +-- o @alice write-tests
| +-- x deploy-staging
| +-- - load-testing
+-- * add-ci
+-- > @alice refactor-auth
+-- o @alice write-tests (-> see above)
Tasks: 1 backlog, 1 ready, 1 in-progress, 1 blocked, 2 done
Viewing Plan Status
Beyond the board, hence provides several commands for inspecting the current state of a plan in different levels of detail.
hence plan status
Dumps all derived conclusions from the reasoner. This is the raw logical output — every fact the reasoner has concluded given the current plan contents. Useful for debugging why a task is or is not in a particular state.
$ hence plan status plan.spl
Definite conclusions:
+D task-setup-repo
+D task-add-ci
+D task-refactor-auth
+D task-write-tests
+D completed-setup-repo
+D completed-add-ci
+D agent-alice-available
...
Defeasible conclusions:
+d task-setup-repo
+d task-add-ci
+d completed-setup-repo
+d completed-add-ci
+d ready-write-tests
+d assign-to-write-tests-alice
+d state-claimed-v1-refactor-auth
+d claimed-refactor-auth
... (and so on)
hence plan summary
A high-level progress overview: counts of tasks in each state, completion percentage, and which agents are currently active.
$ hence plan summary plan.spl
Plan: Backend Refactor Sprint
Status: active
Created: 2026-02-24
Progress: 2/6 tasks done (33%)
Backlog: 1 | Ready: 0 | In Progress: 3 | Blocked: 1 | Done: 2
Agents:
alice: 2 done
bob: 0 done
claude: 0 done
hence plan board --dag
The DAG view renders the full dependency graph as a directed acyclic graph. Each node is a task and each edge represents a dependency. Useful for understanding the critical path.
$ hence plan board plan.spl --dag
Legend: * done o ready > in-progress x blocked - backlog
[* setup-repo]
|
+--------------------+
v v
[* add-ci] [> refactor-auth]
| |
+--------------------+
v
[- write-tests]
|
|
v
[- deploy-staging]
Tasks: 2 backlog, 0 ready, 1 in-progress, 0 blocked, 2 done
hence.run Hosted Plans
When agents are running on different machines — different developer laptops, cloud VMs, CI runners — you need a way to share the plan file without manual copying. hence.run provides hosted plan storage so any agent anywhere can participate in the same plan, supporting up to ~32k simultaneous agents per plan.
Publishing a plan
# Publish your local plan to hence.run
hence remote new plan.spl
Uploaded 12 claims
append: https://hence.run/p/TOKEN... (share with agents)
read: https://hence.run/p/TOKEN... (share with viewers)
admin: https://hence.run/p/TOKEN... (keep private)
Three URLs are returned: the append URL for agents that will write to the plan,
the read URL for viewers, and the admin URL to keep private.
Share the append URL with agents. All commands that accept a local .spl path also
accept a https://hence.run/p/TOKEN URL:
# Another agent on a different machine — same commands, remote URL
export HENCE_AGENT=bob
hence task next https://hence.run/p/abc123
hence task claim api-review https://hence.run/p/abc123
hence task assert '(given api-schema-approved)' https://hence.run/p/abc123
hence task complete api-review https://hence.run/p/abc123
Copying a remote plan locally
If you want to work with a remote plan as a local file — to edit rules, run the REPL, or work
offline — copy it down with hence remote cp:
# Download the remote plan to a local file
hence remote cp https://hence.run/p/abc123 local.spl
# Work locally
hence plan board local.spl
hence repl local.spl
# Copy local changes back to the remote
hence remote cp local.spl https://hence.run/p/TOKEN
Listing known remote plans
# List all remote plans you've interacted with
hence remote ls
TYPE LOCATOR FORMS PEERS LAST SYNCED
----------------------------------------------------------------------------------------
remote hence.run/p/TOKEN... - - 2 min ago
remote hence.run/p/TOKEN... - - 1 hour ago
p2p word-word-word-word 0 0 never
hence installed.
P2P Plans
hence supports a second sharing mode alongside hence.run: fully decentralized peer-to-peer plans. Instead of a server-issued token, a P2P plan is identified by a four-word BIP-39 passphrase. Anyone who knows the passphrase can join the plan; no account or network service is required.
Passphrase structure
The four-word passphrase is not a uniform blob — it is split at the midpoint into two halves with distinct security roles:
abandon-ability — able-about
╰── nameplate ──╯ ╰─ password ─╯
(discovery) (authentication)
| Half | Words | Role | Network exposure |
|---|---|---|---|
| Nameplate | first 2 | Peer discovery — hashed with Argon2id to produce a discovery_id that is published on mDNS (LAN) and the Kademlia DHT (WAN) |
The hash is public. Brute-forcing it reveals that you participate in a plan; it does not reveal the plan contents or encryption keys. |
| Password | last 2 | SPAKE2 key exchange — the full 4-word passphrase is the SPAKE2 input, providing the encryption and authentication keys | Never touches the network in any form. An attacker must guess it via live interactive attempts (detectable, rate-limited). |
Words come from the BIP-39 English wordlist (2048 words, 11 bits each), giving 44 bits of total entropy. The split means brute-forcing the public nameplate half takes ~9 hours on GPU but only reveals plan membership — not content. Cracking the password half requires live SPAKE2 connections (one guess per attempt, rate-limited to ≤ 10/min per peer).
How joining works (SPAKE2)
When you use a passphrase for the first time, hence performs an implicit join automatically
— no separate join command is required. The process:
-
Discovery — hence derives the
discovery_idfrom the nameplate half only using Argon2id, then searches for peers advertising that ID via mDNS on the local network and via Kademlia DHT for cross-network peers. - SPAKE2 handshake — once a peer is found, hence runs a SPAKE2 password-authenticated key exchange using the full 4-word passphrase as the shared password. Both sides derive an identical shared secret without the password ever crossing the wire. A confirmation round verifies both sides used the same passphrase — a wrong passphrase fails here cleanly with no plan data exchanged.
-
Key derivation — HKDF expands the shared secret into three keys:
enc_key(XChaCha20-Poly1305, for encrypting all sync traffic and the local replica at rest),mac_key(HMAC-SHA256, for authenticating broadcast messages), andauth_token(the confirmation step above). - Set-union sync — hence exchanges bloom filters of content-hashed forms with the peer, then transfers only the missing forms. On first join this is the full plan; subsequent syncs transfer only new additions.
-
Caching — the passphrase,
discovery_id, and replica path are stored in~/.config/hence/plans.json. Subsequent commands resolve from cache and skip the SPAKE2 handshake.
# First use — triggers implicit join
hence task next abandon-ability-able-about
Joining plan... done (47 forms, 3 peers)
Next actions for dev:
1. auth @dev — hence task claim auth abandon-ability-able-about --agent dev
# Subsequent use — resolves from cache, incremental sync only
hence task next abandon-ability-able-about
Next actions for dev:
1. auth @dev — hence task claim auth abandon-ability-able-about --agent dev
(synced with 3 peers)
Plan locators and the hence:// URI scheme
The passphrase is a first-class plan locator — it works anywhere a
.spl file path or hence.run URL works. hence detects the locator type from the
argument shape:
| Argument | Mode |
|---|---|
plan.spl | Local file |
https://hence.run/p/TOKEN | Hosted (hence.run) |
word-word-word-word (4 BIP-39 words) | P2P passphrase |
hence://word-word-word-word | P2P URI (equivalent to bare passphrase) |
The hence:// URI extends the bare passphrase with optional metadata useful
for digital sharing (chat, docs, QR codes):
# Bare passphrase — optimised for voice, whiteboard, conversation
hence task next abandon-ability-able-about
# Full URI — carries bootstrap hints for WAN peer discovery
hence task next "hence://abandon-ability-able-about?bootstrap=node1.example.com:4001"
# Bootstrap hints tell hence where to look for peers before trying the DHT
# — useful on private networks or when WAN Kademlia discovery is slow
Bootstrap hints in the URI are cached locally, so after the first join you can use the bare passphrase and hence will reuse the cached addresses.
Creating a P2P plan
Pass --p2p to hence remote cp when copying a local plan. hence
generates a random passphrase and creates a local encrypted replica:
# Publish a local plan as a P2P plan
hence remote cp sprint.spl --p2p
abandon-ability-able-about
Share this passphrase with other agents.
Use it anywhere you would use a local .spl file.
The passphrase is the plan's permanent identifier. Share it with collaborators by any channel. All plan data is end-to-end encrypted — the passphrase is both the address and the key.
Using a P2P plan
Pass the passphrase (bare or as a hence:// URI) wherever you would normally pass a
.spl file:
# Every hence command accepts a passphrase as the plan argument
export HENCE_AGENT=alice
hence plan board abandon-ability-able-about
hence task next abandon-ability-able-about
hence task claim setup abandon-ability-able-about
hence task complete setup abandon-ability-able-about
# Or using the hence:// URI scheme (equivalent)
hence task next hence://abandon-ability-able-about
On each read command, hence pre-syncs with any available peers (up to 2 s) to fetch the latest state. On each write command, hence post-syncs (up to 5 s) to push your changes out. Commands work offline using the local cached replica when no peers are reachable.
Exporting to a local file
# Download the current state of a P2P plan to a local file
hence remote cp abandon-ability-able-about local.spl
# Upload a local file's forms into a P2P plan (syncs first, then appends)
hence remote cp local.spl abandon-ability-able-about
Persistent sync daemon
For long-running deployments — a fleet of agents on separate hosts, or a plan that needs to stay current between commands — start the persistent daemon:
# Start the P2P sync daemon for all registered plans (runs in foreground)
hence remote serve
Listening on /ip4/0.0.0.0/tcp/4001
Syncing 2 plans...
The daemon maintains a live libp2p swarm. Peers discover each other via mDNS on the local network and via the Kademlia DHT for cross-network discovery. When a peer announces new forms, the daemon syncs immediately via an encrypted request-response exchange.
Stopping management of a P2P plan
# Remove a P2P plan from this machine (pass passphrase, or pipe it from stdin)
hence remote forget abandon-ability-able-about
Removed local replica. Other peers still retain their copies.
hence remote forget deletes the local encrypted replica and clears cached
credentials. Other peers are unaffected and continue syncing.
hence.run vs P2P: choosing a mode
| Aspect | hence.run (hosted) | P2P passphrase |
|---|---|---|
| Identifier | https://hence.run/p/TOKEN |
word1-word2-word3-word4 |
| Infrastructure | Centralized server | Peer-owned, no server required |
| Encryption | TLS in transit | End-to-end (XChaCha20-Poly1305) |
| Works offline | No | Yes — cached locally |
| Setup | hence remote new → get URL |
hence remote cp --p2p → get passphrase |
| Sharing | Share URL | Share 4-word passphrase |
| Best for | Teams, CI, easy onboarding | Air-gapped, privacy-sensitive, or offline-first workflows |
hence remote cp. You can mirror a hence.run plan to
P2P or vice versa at any time: hence remote cp https://hence.run/p/TOKEN --p2p
creates a P2P fork with all the same forms.
The REPL for Interactive Exploration
The hence REPL provides an interactive query session against a plan's logic. It is the fastest way to debug why a task is or is not ready, understand how rules interact, and explore the consequences of hypothetical facts.
# Start an interactive session against a plan
hence repl plan.spl
hence repl — type :help for commands, :quit to exit
> query ready-write-tests
true (derived via assign-to-write-tests-alice, task-write-tests, agent-alice)
> query in-progress-refactor-auth
true (derived via claims-refactor-auth-alice, task-refactor-auth)
> why blocked-deploy-staging
true
rule: normally blocked-deploy-staging given staging-unavailable
support: (given staging-unavailable) — asserted by alice at 2026-02-24T10:15:00Z
> assume staging-available
Hypothetically assuming: staging-available
Now querying with this extra fact...
> query blocked-deploy-staging
false (staging-available defeats staging-unavailable block rule)
> :quit
REPL commands
| Command | Description |
|---|---|
query FACT |
Ask whether a fact is currently derived. Returns true/false with derivation chain. |
why FACT |
Show the full justification for why a fact is (or is not) derived, including which rules fired and which premises they depended on. |
assume FACT |
Temporarily add a hypothetical fact for subsequent queries without writing to the plan file. Useful for "what if" analysis. |
retract FACT |
Remove a previously assumed hypothetical fact. |
list |
List all currently derived facts, equivalent to hence plan status. |
:reload |
Reload the plan file from disk, picking up any changes made since the session started. |
:quit |
Exit the REPL. No changes are written to the plan file during a REPL session unless you use assert. |
why ready-TASKNAME to see which premises are missing. Then use
assume PREMISE to confirm your hypothesis before asserting it for real.
Supervised Execution
The manual loop — hence task next → claim → work → assert → complete → repeat —
works well for human operators and for LLMs that manage their own tool calls. For fully
automated, unattended execution, hence provides two supervised commands that handle the loop
for you.
hence agent watch --spawn --agent NAME — the supervisor loop
This is the primary command for running a plan end-to-end without manual intervention. It watches the plan continuously and spawns a supervised agent process for each task as it becomes ready, driving the entire plan to completion.
# Drive a full plan to completion with Claude
hence agent watch plan.spl --spawn --agent claude
# Same, with event logging and automatic worktree cleanup
hence agent watch plan.spl --spawn --agent claude \
--cleanup \
--events events.jsonl \
--session my-run
The watch loop runs until all tasks are done or a terminal failure occurs. While it runs, it emits status to the terminal and (optionally) NDJSON events to a file for monitoring. Each spawned task gets its own isolated git worktree so concurrent tasks do not interfere.
--agent to your LLM
backend, add --session "${CI_BUILD_ID}" for log correlation, and walk away.
See Supervision for details on lease management, liveness
monitoring, retries, and failure propagation.
hence agent spawn — one-off task execution
hence agent spawn executes a single task with full supervision
and exits. The watch loop uses it internally for each task it picks up. Use it directly
when you want to run one specific task and inspect the result before proceeding.
# Execute the next available task (auto-selected)
hence agent spawn plan.spl --agent claude
# Target a specific task
hence agent spawn plan.spl --task task-deploy --agent claude
# Dry-run: show the assembled prompt without executing
hence agent spawn plan.spl --dry-run --show-prompt
Manual loop vs supervised loop
| Approach | Command | Best for |
|---|---|---|
| Manual loop | hence task next → claim → work → complete |
Human operators; LLMs managing their own tool calls; step-by-step debugging |
| One-off spawn | hence agent spawn plan.spl --agent NAME |
Running a single task automatically; scripted pipelines; testing supervision behaviour |
| Supervisor loop | hence agent watch plan.spl --spawn --agent NAME |
Fully automated, unattended execution; CI; driving an entire plan hands-free |
Task Decomposition
When an agent discovers a task is too large for a single pass, it can decompose the task
into subtasks. hence plan translate creates plans from scratch;
hence plan decompose expands a single task within an existing plan.
Decomposing a task (human or external agent)
# Agent discovers task-auth is too complex — decompose it
hence plan decompose auth plan.spl --agent claude --merge
# Or write subtasks to a separate file for review first
hence plan decompose auth plan.spl --agent claude -o auth-sub.spl
The command uses abductive reasoning (require completed-{TASK}) to tell the LLM
what facts must be proved, then validates the generated subtasks against the parent plan.
With --merge, the subtasks are appended directly to the parent plan and the
watch supervisor can spawn them immediately.
Agent-reentrant decomposition (when you are the LLM)
An LLM agent cannot spawn a nested instance of itself (Claude Code blocks child sessions,
other agents have similar guards). The --prompt-only and --stdin
flags solve this by separating orchestration from generation:
# Step 1: Get the assembled prompt (hence does orchestration)
PROMPT=$(hence plan decompose auth plan.spl --prompt-only)
# Step 2: Agent processes $PROMPT internally and generates SPL...
# Step 3: Feed back for validation + merge (hence does orchestration)
echo "$SPL" | hence plan decompose auth plan.spl --stdin --merge
If validation fails (--stdin exits with code 2), read the error, regenerate
the SPL, and call --stdin again. Use --json on both flags for
structured machine-parseable output.
Decompose during supervised execution
Decompose integrates naturally with hence agent watch --spawn. When a spawned
agent determines its task is too large, it can decompose the task inline. The watch supervisor
detects the new subtasks on its next poll cycle and spawns agents for them automatically.
# Supervisor is watching the plan
hence agent watch plan.spl --spawn --agent claude
# A spawned agent discovers task-build-api needs subtasks.
# Since it's already an LLM, it uses prompt-only + stdin:
# PROMPT=$(hence plan decompose build-api plan.spl --prompt-only)
# # ... agent generates SPL from $PROMPT ...
# echo "$SPL" | hence plan decompose build-api plan.spl --stdin --merge
#
# Watch detects new ready subtasks → spawns agents for them
# When all subtasks complete → completed-build-api is derived
See the LLM Guide for more on when to decompose and how to choose between automatic and manual subplans.
Process Mining
hence can learn plan patterns from execution history. Process mining extracts event logs from completed plans and discovers rules that explain observed behavior. All mutation commands automatically add timestamps, so completed plans are ready for analysis.
Extracting event logs
Convert completed plans into a structured event log:
# Extract events from multiple plan files
hence learn extract-log plans/*.spl --format json > events.json
# View summary
hence learn extract-log plans/*.spl --format summary
Learning rules
Mine defeasible rules from execution traces:
# Output learned rules as DFL
hence learn rules plans/*.spl --format dfl
# View mining summary
hence learn rules plans/*.spl --format summary
The miner identifies ordering patterns (e.g. "models always completes before crud") and generates defeasible rules with support and confidence scores.
Validating against existing rules
Compare learned patterns against your plan template to find gaps:
hence learn validate-rules plans/*.spl --against template.spl
This identifies:
- New patterns — rules observed in practice but missing from the template
- Conflicts — learned behavior that contradicts existing rules
- Low confidence rules — patterns that vary across traces (may need defeaters)
Putting It All Together
Here is a complete agent session — from identity setup through multiple task completions — showing how the commands compose in practice:
# 1. Set identity once for the session
export HENCE_AGENT=claude
# 2. Orient: what plan are we working on?
hence plan info plan.spl
hence plan summary plan.spl
# 3. See the full picture
hence plan board plan.spl
# 4. Find MY tasks
hence task next plan.spl
# → write-tests [READY] hence task claim write-tests plan.spl
# → update-docs [READY] hence task claim update-docs plan.spl
# 5. Claim the first task
hence task claim write-tests plan.spl
# 6. Do the work (run test suite, verify coverage, etc.)
npm test
# ... all tests pass, coverage at 87% ...
# 7. Record findings
hence task assert '(given tests-passing)' plan.spl --task write-tests
hence task assert '(given coverage-above-80)' plan.spl --task write-tests
# 8. Mark the task done
hence task complete write-tests plan.spl
# 9. Loop — find the next task (update-docs may still be there, or
# new tasks may have unlocked due to tests-passing)
hence task next plan.spl
# 10. Claim the next task
hence task claim update-docs plan.spl
# ... and so on until no tasks remain assigned to us ...
hence task next plan.spl
# → No tasks currently assigned to claude. All done or waiting on others.
# Check overall plan progress
hence plan summary plan.spl
Remote workflow (multi-machine)
# Machine A — plan author publishes the plan
hence remote new sprint.spl
# → https://hence.run/p/abc123
# Machine B — first agent joins
export HENCE_AGENT=alice
hence task next https://hence.run/p/abc123
hence task claim setup https://hence.run/p/abc123
# ... work ...
hence task complete setup https://hence.run/p/abc123
# Machine C — second agent joins (independently)
export HENCE_AGENT=claude
hence task next https://hence.run/p/abc123
# → setup is now DONE; write-tests is now READY (unlocked)
hence task claim write-tests https://hence.run/p/abc123
setup was recorded in the hosted plan, and Claude's hence task next
query automatically reflected the new state. The reasoner on each machine derives the current
truth from the accumulated facts in the plan — there is no shared mutable state to synchronize.
Quick Reference
| Command | What it does |
|---|---|
hence agent whoami |
Print current agent identity and public key |
hence agent watch PLAN --spawn --agent NAME |
Supervisor loop — watch and spawn agents for ready tasks until plan is complete |
hence agent spawn PLAN --agent NAME |
Execute a single task with full supervision and exit |
hence plan info PLAN |
Show plan metadata: title, agents, task count |
hence plan board PLAN |
Show full kanban board with all task states |
hence plan board PLAN --tree |
Show dependency tree view |
hence plan board PLAN --dag |
Show DAG view |
hence plan board PLAN --json |
Machine-readable board output |
hence plan status PLAN |
Dump all derived logical conclusions |
hence plan summary PLAN |
Progress overview with counts and percentages |
hence task next PLAN |
Show tasks assigned to the active agent |
hence task next PLAN --json |
Machine-readable assigned task list |
hence task assign PLAN |
Show all assignments across all agents |
hence task claim TASK PLAN |
Claim a task (move to IN PROGRESS) |
hence task unclaim TASK PLAN |
Release a claim (move back to READY) |
hence task assert 'EXPR' PLAN |
Assert a fact or rule into the plan |
hence task assert 'EXPR' PLAN --task TASK |
Assert a fact tagged with the current task |
hence task complete TASK PLAN |
Mark a task done |
hence task block TASK "REASON" PLAN |
Mark a task blocked with explanation |
hence task unblock TASK PLAN |
Remove a block, returning task to prior state |
hence repl PLAN |
Start interactive query session |
hence remote new [FILE] |
Create a new hosted plan on hence.run, returns URL |
hence remote cp SRC [DST] |
Copy between local file, P2P passphrase, and hence.run URL |
hence remote cp FILE --p2p |
Publish a local plan as a new P2P plan, prints passphrase |
hence remote ls |
List all known plans (local, P2P, hosted) |
hence remote serve |
Start persistent P2P sync daemon for all registered plans |
hence remote forget [PASSPHRASE] |
Remove a P2P plan's local replica and credentials |
Continue reading: Supervision covers how to set up agent supervisors that monitor task health and enforce liveness guarantees. LLM Integration covers embedding hence commands into LLM agent prompts and tool loops. See the CLI Reference for every flag and option.