summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md6
-rw-r--r--spec/test_luatool.lua4
-rw-r--r--subagents/workflow.lua11
3 files changed, 15 insertions, 6 deletions
diff --git a/README.md b/README.md
index e985c18..6841ed9 100644
--- a/README.md
+++ b/README.md
@@ -142,8 +142,10 @@ starts model-authored workflows in a restricted environment and returns a
session-scoped workflow ID immediately. Work continues on Pantograph's event
loop; completion wakes the primary, and later calls can inspect field-read-only
records through `subagents.workflows[id]`, including named child status and
-outputs. Every `ctx:agent` needs a workflow-unique `name`, and the callback must
-return the workflow's string result.
+outputs. While one is live the extension emits balanced `background_work_start`
+and `background_work_end` events, allowing lifecycle integrations to remain
+busy across the primary turn boundary. Every `ctx:agent` needs a workflow-unique
+`name`, and the callback must return the workflow's string result.
The same read-only workflow records are exposed to other extensions as
`panto.ext.workflows`. Extensions can iterate this table or look up an ID; each
diff --git a/spec/test_luatool.lua b/spec/test_luatool.lua
index e7f2294..ee0a79e 100644
--- a/spec/test_luatool.lua
+++ b/spec/test_luatool.lua
@@ -112,7 +112,9 @@ return {
assert(record.agents.review.status == "completed")
assert(#handle.submissions == 1, "completion wakes the primary once")
has(handle.submissions[1], id)
- assert(handle.emitted[1] == "agent_submission", "the host pipeline is explicitly woken")
+ assert(table.concat(handle.emitted, ",") ==
+ "background_work_start,agent_submission,background_work_end",
+ "background work brackets the primary wake")
end)
end },
diff --git a/subagents/workflow.lua b/subagents/workflow.lua
index 671890e..ff534cb 100644
--- a/subagents/workflow.lua
+++ b/subagents/workflow.lua
@@ -748,6 +748,11 @@ local function make_workflow_record(id)
return record
end
+local function emit(name)
+ local ext = host()
+ if type(ext.emit) == "function" then pcall(ext.emit, name) end
+end
+
local function notify(record)
if record.suppress_notification or record.status == "cancelled" then return end
local primary = host().agent
@@ -755,9 +760,7 @@ local function notify(record)
local submitted = pcall(primary.submit, primary, string.format(
"[subagents] Workflow %s %s. Inspect subagents.workflows[%q] with subagents.lua.",
record.id, record.status, record.id))
- if submitted and type(host().emit) == "function" then
- pcall(host().emit, "agent_submission")
- end
+ if submitted then emit("agent_submission") end
end
local function finish_workflow(record, status, result, err)
@@ -769,6 +772,7 @@ local function finish_workflow(record, status, result, err)
active_workflows[record.id] = nil
progress.workflow_finished(record.tool_call_id)
notify(record)
+ emit("background_work_end")
end
-- Start a model-authored workflow on its own coroutine and return before the
@@ -826,6 +830,7 @@ function M.start(wf, opts)
end
end)
progress.workflow_started(record.tool_call_id)
+ emit("background_work_start")
return id
end