Skip to content

feat: run a subagent's lich session in the background, and let lich turn it off - #32

Merged
omartelo merged 1 commit into
mainfrom
feat/cards-async
Oct 5, 2026
Merged

omartelo merged 1 commit into
mainfrom
feat/cards-async

Conversation

@omartelo

@omartelo omartelo commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator

Why

The subagent card held the asking turn for the whole run (chunked lich wait), while a native subagent runs in the background. And lich now lets the user turn cards off.

What

  • After lich open hands the task over, the Agent call returns Claude Code's async_launched arm at once (outputFile: "", what Claude Code itself uses for an agent with no output file). A context line tells the model the report arrives as a [lich] note, collected with wait_for_answer / lich wait, and that SendMessage cannot reach the worker. The chunked wait and its deny paths are gone (named in the commit).
  • LICH_SUBAGENT_CARDS=off (set by lich's new setting, omartelo/lich feat/subagent-cards-setting) leaves every Agent call native.

Tests

node 265/265, claude plugin test . 16/16, validate ok. Live on 2.1.289 with a fake lich: "Backgrounded agent", turn ended in 5s, the model named the [lich] path; with the variable off the native agent ran. Not live: the [lich] note arriving from a real lich.

…urn it off

Once lich open hands the task over, the Agent call answers with Claude
Code's async_launched arm at once instead of holding the asking turn on
chunked lich wait calls. The report comes back as an ordinary lich errand:
a [lich] note at the asking session's prompt, collected with
wait_for_answer or lich wait. A context line after the result tells the
model so, and that SendMessage cannot reach the worker. outputFile is "",
Claude Code's own value for an agent with no output file; without
canReadOutputFile it is never shown to the model.

A session started with LICH_SUBAGENT_CARDS=off (lich's "Subagents as lich
sessions" setting, off) leaves every Agent call native.

Tests removed because the contract they pinned is gone (nothing waits
after the open anymore): the chunked wait, "a wait that failed after the
task reached the worker is denied" and "Esc during the wait stops the
wait". The unread/undelivered, unanswered and unknown-status tests now
read the status off the open's delivery, where the wait used to supply
it; their outcomes are unchanged.
@omartelo
omartelo merged commit 7406f1d into main Oct 5, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant