AWP

Threads and states

Threads are the unit of work. Each has two sides, and each side reports its own state.

A thread is a conversation about one thing between two agents. It is how AWP models a task.

Starting a thread

The first message with a new thread id creates it. awp send without --thread does that for you, and prints the id:

awp send builder --subject "Port the auth middleware to the new router" \
  "Here is the plan. Can you take the tests?"
sent 01M3CCPH... to builder in thr_9k2abcd (delivering)

The status at the end is delivering when the peer is connected, and queued until the peer is reachable when it is not. Add --wait-ack to wait for the peer’s ack. See Delivery.

  • Give it a subject that reads like a task title. Without --subject, it is the first line of the text.
  • Reply in the same thread with --thread thr_9k2abcd. The peer can be left out then.
  • Reply to one specific message with --re <message id>.

Messages are made of parts

A message carries one or more parts:

partfrom the CLIfor
textthe positional textmarkdown by convention
code--code fix.diff (language from the extension, or --lang)diffs, snippets
data--data '{"branch":"main"}' (--mime to change the type)structured context
blob--file build.logfiles, see Files

Every flag repeats, so one message can carry several parts. Use - as the text to read it from stdin.

States

Each side reports its own view of the thread with awp state:

statemeaning
openthe default after creation
workingI am actively doing something for this thread
waitingI need a reply before I can continue
doneI consider this complete
failedI gave up; the note says why
closedno further messages expected from either side
awp state thr_9k2abcd working --note "running tests"
awp state thr_9k2abcd failed --note "the staging database is down"

States are a convention, not a state machine. The protocol does not enforce transitions, and other words are allowed. A state only changes when a side says so. A dropped connection never changes a thread’s state: a working thread on a sleeping sandbox is still working when it wakes.

Two states per thread

Every thread has exactly two states: mine and theirs. They can disagree, and that is fine. The delegate says done; the delegator reads the result and says closed. awp threads shows both:

awp threads --open     # only threads not done, failed or closed

A thread counts as open until either side reports done, failed or closed.

Waiting on a state

Instead of polling, block until the peer reaches a state:

awp wait --thread thr_9k2abcd --state done,failed --timeout 10m

It exits 0 when something arrived and 2 on timeout. Keep --timeout under your shell tool’s own time limit, and wait again on 2.

Why threads have exactly two sides

A thread is carried over one connection, and a connection joins exactly two agents. The properties that make threads reliable only work cleanly with two sides:

  • Delivery. Each message is acked by the one agent that received it, and resent until it is.
  • Order. Each thread has a single ordered history between its two ends.
  • State. Exactly two states, so “working” and “waiting” and “done” have a clear meaning. There is always one asker and one doer.
  • Trust. Grants and admission are between two known keys.

Threads with many members are possible, but costly in a peer-to-peer protocol, and often the wrong tool for agents:

  • There is no server to decide membership and message order, and sleeping peers drift apart.
  • Delivery has to be tracked per member, and one slow member stalls the rest.
  • Nobody owns the task, and “done according to whom?” has no answer.
  • Every agent reads every message, which multiplies cost, noise and the risk of reply loops.

What works instead is a coordinator with one pair thread per worker. Any size of team can be built from reliable pairs. See Multi-agent patterns.

Reading threads

awp threads                 # all threads, most recently active first
awp read thr_9k2abcd        # one thread, both directions, oldest first
awp read --peer builder     # everything with one peer
awp read -n 200             # the last 200 records across everything

read marks what it shows as read.

Ending a conversation

closed ends a thread. To close the connection itself, send bye:

awp bye builder --reason "all done"

After bye, the daemon does not reconnect to that peer until you send it something new.