Choosing a Surface¶
lionagi's CLI has several orchestration surfaces. They are layered, not competing: each one buys you something over the previous layer and costs something in latency and setup. This page is the decision guide; per-flag detail lives in the CLI Reference.
The decision table¶
| Your task shape | Reach for | Why |
|---|---|---|
| One question, one answer | li agent MODEL "prompt" | Single turn, no planning overhead |
| Follow-up on earlier work | li agent -r BRANCH_ID / -c | Resumes the branch with full context |
| Same role used often | li agent -a NAME | Profile carries model, effort, system prompt, yolo |
| N independent subtasks, same shape | li o fanout | Decompose → parallel workers → optional synthesis |
| Subtasks depend on each other | li o flow | Planner builds a DAG; engine runs legs as dependencies clear |
| A pipeline you run repeatedly | li play NAME | Playbook = named, parametric, version-controlled flow |
| A well-known domain pipeline | li engine run KIND | Prebuilt research / review / coding / hypothesis / planning engines |
| Run it later, or on a cadence | li schedule create | Cron, interval, or repo-event triggers |
| Script must wait for a scheduled run to finish | li monitor run ID | Takes a schedule-run ID; blocks until terminal state, exit code reflects outcome |
| Watch progress live | li monitor --watch | Live table or per-run detail view |
| Agents messaging each other across runs | li team | Persistent shared inbox |
| Group many runs into one record | li invoke | One parent invocation row grouping N session rows |
Sizing: don't pay for structure you don't need¶
Each layer adds a planning or coordination step that costs real wall-clock time before any work starts. The single most common misuse is reaching for a heavier surface than the task shape needs:
- 1 leg →
li agent. Neverli o flow— you would pay a planner turn to produce a one-node DAG. - 2–3 independent legs →
li o fanout, or just twoli agentcalls in parallel from your own script. Fanout's decomposition phase only earns its cost when you want the orchestrator to choose the split. - 3+ legs with dependencies →
li o flow. This is the break-even point: below it the planner turn dominates; above it dependency-aware parallelism wins. - The same flow, more than twice → promote it to a playbook and use
li play. The point of a playbook is that the second invocation is one short command with typed args — not that the first one is faster.
The corollary: li play feeling slow is usually a shape problem, not an engine problem. A playbook wrapping a 2-leg task inherits the full plan-then-execute cycle. Check the DAG with --dry-run — if it plans one or two nodes, drop down a layer.
Composition patterns¶
The surfaces are designed to chain:
# Recurring pipeline: schedule an agent turn on a cron. Create prints
# the schedule ID; trigger and runs take that ID, not the name.
SCHED=$(li schedule create nightly-audit --cron "0 6 * * *" \
--action-kind agent --agent auditor --model sonnet \
--prompt "run the nightly audit" | awk '/^Created:/ {print $2}')
# Fire it now, then list its firings — each row carries a run ID and
# outcome. (Direct `li play` runs are watched with `li monitor --watch`.)
li schedule trigger "$SCHED"
li schedule runs "$SCHED"
# Copy a run ID from that listing, then block until it goes terminal
li monitor run "$RUN_ID" && echo "audit done"
# One dashboard row for a multi-run skill
INV=$(li invoke start --skill release-check --prompt "v0.28 gate")
li play backend --invocation "$INV"
li play frontend --invocation "$INV"
li invoke end "$INV" --status completed
# Resume a worker that a fanout or flow left unfinished
li agent -r BRANCH_ID "pick up where you left off"
Two rules of thumb for choosing the chain:
- Automate the trigger before automating the pipeline. If you find yourself re-typing the same
li playinvocation daily, the next step isli schedule, not a bigger playbook. - Poll the surface, not the filesystem.
li monitorandli monitor runread the same state the engine writes; tailing run directories or sleeping in shell loops re-implements them badly.
What each layer persists¶
All surfaces share one state database, but what each writes differs:
li agent/li o fanout/li o flow/li playwrite a run directory under~/.lionagi/runs/(branch snapshots, stream buffers) plus session rows in the state database. A flow or fanout leg is a branch you can resume withli agent -r.li engine runwrites an engine-run row and its session rows to the state database only — no run directory.li invokewrites one parent invocation row; the runs you attach to it keep their own persistence.li schedule createwrites schedule metadata; each firing records a schedule run, listed byli schedule runs ID.
Because the state database is shared, anything you start on one surface is observable from the others, and escalating a task to a heavier surface never orphans the work the lighter one already did.