Attach

Watch, steer, or interrupt a live session running on the warm runtime

praisonai attach connects a second terminal to a live agent session on the warm runtime. By default it streams events read-only; with --message it steers the live turn, and with --interrupt it cancels it — both as one-shot sends that exit without streaming.

Diagram

SSE events

SSE events

POST steer/interrupt

run.steer / run.interrupt

run.steer / run.interrupt

Terminal A
run –attach id

Warm Runtime

Terminal B
attach id

Terminal C
attach id –json

Terminal D
attach -m / –interrupt id

Quick Start

  1. Start the warm runtime
    bash
    praisonai daemon start --background
  2. Run an agent with a session id (terminal A)
    bash
    praisonai run "Research topic X" --attach my-session
  3. Attach from another terminal (terminal B)
    bash
    praisonai attach my-session
  4. Steer the live turn from another terminal
    bash
    praisonai attach -m "also update the tests" my-session

    Sends the steering message and exits. The running agent picks it up on its next tool-loop iteration.

  5. Interrupt the live turn from another terminal
    bash
    praisonai attach --interrupt my-session

    Requests a cooperative cancel and exits. The run stops at the next safe boundary.


Usage

bash
praisonai attach [--json] [--message TEXT] [--interrupt] <session-id>
Argument / OptionTypeDefaultDescription
session_idpositionalrequiredSession id to attach to
--jsonflagfalseEmit raw NDJSON events instead of human-readable output
--message, -mstringNoneSteer the live turn with this message, then exit (no streaming)
--interruptflagfalseRequest a cooperative cancel of the live turn, then exit (no streaming)

Steering a live turn

Send mid-run guidance to a session that is already executing on the warm runtime; it lands on the agent’s next tool-loop iteration without restarting the run.

bash
# Terminal A — start a long-running agent on the warm runtime
praisonai run "Research solar market trends and write a 500-word summary" --attach my-session

# Terminal B — steer it mid-run
praisonai attach -m "Focus on the EU market only" my-session

# Terminal B (optional) — stop it early
praisonai attach --interrupt my-session
User (Term A):  praisonai run "research solar market trends..." --attach my-session
Agent:          (searching → reading → summarising …)
User (Term B):  praisonai attach -m "focus on the EU market only" my-session
Agent:          (next iteration picks up guidance, re-scopes the next search)
User (Term B):  praisonai attach --interrupt my-session
Agent:          ■ run.interrupt requested — stops at next safe boundary

Interrupting a live turn

--interrupt requests a cooperative cancel; the agent stops at the next safe boundary, so partial progress and conversation history stay intact.

bash
praisonai attach --interrupt my-session

Which flag do I want?

Diagram

Just watch events

Send new guidance mid-run

Stop the current turn

Pipe JSON to a tool

Attached to a running session

What do I want?

praisonai attach id

praisonai attach -m text id

praisonai attach –interrupt id

praisonai attach –json id

Both flags can be combined (-m "focus" --interrupt <id>): the message is sent first, then the interrupt.


How It Works

Diagram
Terminal C (attach -m / –interrupt)Terminal B (attach)Live AgentWarm RuntimeTerminal A (run –attach)Terminal C (attach -m / –interrupt)Terminal B (attach)Live AgentWarm RuntimeTerminal A (run –attach)/run (session=my-session)agent.start(prompt)GET /sessions/my-session/events (SSE)run.startPOST /sessions/my-session/steer {message}agent.steer(message, priority=5)run.steer {message}POST /sessions/my-session/interruptinterrupt request (“attach”)run.interrupt {reason: “attach”}result (or clean stop)run.result

Attaching never starts execution; plain attach only observes, while -m and --interrupt act on a turn already in flight (not gated by the run lock). Detaching (Ctrl-C) does not stop the run on terminal A.


Event Reference

TypeFieldsHuman render
run.startsession_id, prompt▶ run.start: <prompt>
run.resultsession_id, ok, result✓ run.result then result text
run.errorsession_id, error✗ run.error: <error>
run.steersession_id, message↪ run.steer: <message>
run.interruptsession_id, reason■ run.interrupt requested

Human output

Attached to session 'my-session'. Ctrl-C to detach.
▶ run.start: Research topic X
✓ run.result
Here is the summary...

–json (NDJSON)

bash
praisonai attach my-session --json | jq 'select(.type=="run.result")'
json
{"type": "run.start", "session_id": "my-session", "prompt": "Research topic X"}
{"type": "run.steer", "session_id": "my-session", "message": "Focus on the EU market only"}
{"type": "run.interrupt", "session_id": "my-session", "reason": "attach"}
{"type": "run.result", "session_id": "my-session", "ok": true, "result": "..."}

Exit Codes

CodeMeaning
0Clean detach (Ctrl-C), or steer/interrupt sent
1No compatible warm runtime, runtime lacks steer/interrupt support, or stream lost mid-attach
4Runtime module not importable

Common Patterns

Watch a long-running agent from a second terminal — start with --attach, observe progress without blocking terminal A.

Pipe JSON into jq — praisonai attach my-session --json | jq 'select(.type=="run.result")'.

Multiple observers — several terminals can attach to the same session concurrently; all receive the same events.

Observe without persisting — praisonai run "..." --no-save --attach obs-1 streams events under obs-1 for observers while keeping the run on the anonymous, non-persisted path.

Steer a long multi-tool run from a second terminal — praisonai attach -m "focus on the EU market only" my-session lands on the next tool-loop iteration without restarting the run.

Stop a stuck turn without losing the session — praisonai attach --interrupt my-session cancels the current turn only; the next run --session my-session continues from where it left off.


Best Practices

Start the daemon first

Run praisonai daemon start before run --attach. Without a warm runtime, attach exits with code 1.

Use direct prompt runs only

--attach on praisonai run works for direct prompts only — not YAML files, --agent, or --command.

Detaching is safe

Ctrl-C in an attach terminal never cancels the underlying agent run.

One-shot steer and interrupt, not an interactive loop

-m and --interrupt send one request and exit. Run them again from a second terminal as needed; there is no persistent input loop inside attach.

Older daemon? Restart it after upgrading

If attach -m or attach --interrupt prints runtime does not support …, the warm daemon pre-dates PR #5847. Run praisonai daemon stop && praisonai daemon start to pick up the new routes.

Version mismatch after upgrade

If CLI and daemon major versions differ, attach refuses to connect. Run praisonai daemon stop && praisonai daemon start after upgrading.


Related