local common_agent_script = [[
-- _agent_config is injected by spawn_common_agent() before this script.
-- Fallback defaults for direct usage / testing:
if not _agent_config then
_agent_config = { name = "common-agent", subscriptions = {"AgentTask"} }
end
local _name = _agent_config.name or "common-agent"
-- IntentDef registration guard: register skills/delegate/agent intents once per VM.
-- process() is called on every LLM turn; IntentDefs are idempotent but wasteful.
local _intents_registered = false
return {
id = _name,
namespace = "agent",
subscriptions = _agent_config.subscriptions or {},
-- operation="process" — main LLM processing (from AgentTask event or RPC)
-- NOTE: When invoked via event (fire-and-forget), the return value of
-- on_request is discarded by the runtime. Output and observability are
-- handled inside emit_success() / orcs.output_with_level().
-- operation="ping" — lightweight connectivity check (from init RPC)
on_request = function(request)
local input = request.payload or {}
local operation = request.operation or "process"
-- Build LLM opts from config passed via event payload or RPC payload
local function build_llm_opts(input)
local opts = {}
local llm_cfg = input.llm_config or {}
if llm_cfg.provider then opts.provider = llm_cfg.provider end
if llm_cfg.model then opts.model = llm_cfg.model end
if llm_cfg.base_url then opts.base_url = llm_cfg.base_url end
if llm_cfg.api_key then opts.api_key = llm_cfg.api_key end
if llm_cfg.temperature then opts.temperature = llm_cfg.temperature end
if llm_cfg.max_tokens then opts.max_tokens = llm_cfg.max_tokens end
if llm_cfg.timeout then opts.timeout = llm_cfg.timeout end
if llm_cfg.max_tool_turns then opts.max_tool_turns = llm_cfg.max_tool_turns end
return opts
end
-- Output LLM response to IO and emit observability event
local function emit_success(message, llm_resp)
orcs.output(llm_resp.content or "")
orcs.emit_event("Extension", "llm_response", {
message = message,
response = llm_resp.content,
session_id = llm_resp.session_id,
cost = llm_resp.cost,
source = _name,
})
orcs.log("debug", string.format(
"%s: completed (cost=%.4f, session=%s)",
_name, llm_resp.cost or 0, llm_resp.session_id or "none"
))
end
-- Ping: lightweight connectivity check (no tokens consumed)
if operation == "ping" then
local ping_opts = build_llm_opts(input)
local ping_resp = orcs.llm_ping(ping_opts)
return {
success = ping_resp.ok,
data = ping_resp,
}
end
local message = input.message or ""
-- Session resumption: skip full prompt assembly, send message directly
if input.session_id and input.session_id ~= "" then
orcs.log("debug", _name .. ": resuming session " .. input.session_id:sub(1, 20))
local opts = build_llm_opts(input)
opts.session_id = input.session_id
opts.resolve = true
opts.hil_intents = true -- Propagate Suspended for HIL approval
local llm_resp = orcs.llm(message, opts)
if llm_resp and llm_resp.ok then
emit_success(message, llm_resp)
return {
success = true,
data = {
response = llm_resp.content,
session_id = llm_resp.session_id,
num_turns = llm_resp.num_turns,
cost = llm_resp.cost,
source = _name,
},
}
else
local err = (llm_resp and llm_resp.error) or "llm resume failed"
orcs.output_with_level("[" .. _name .. "] Error: " .. tostring(err), "error")
return { success = false, error = err }
end
end
-- First call: full prompt assembly
local history_context = input.history_context or ""
local delegation_context = input.delegation_context or ""
local placement = input.prompt_placement or "both"
-- 0a. Fetch foundation segments (system/task/guard from agent.md)
local f_system = ""
local f_task = ""
local f_guard = ""
local f_resp = orcs.request("foundation::foundation_manager", "get_all", {})
if f_resp and f_resp.success and f_resp.data then
f_system = f_resp.data.system or ""
f_task = f_resp.data.task or ""
f_guard = f_resp.data.guard or ""
else
orcs.log("debug", _name .. ": foundation segments unavailable, proceeding without")
end
-- 0b. Fetch console metrics (git, cwd, timestamp)
local console_block = ""
local m_resp = orcs.request("metrics::console_metrics", "get_all", {})
if m_resp and m_resp.success and m_resp.formatted then
console_block = m_resp.formatted
else
orcs.log("debug", _name .. ": console metrics unavailable, proceeding without")
end
-- 1. Gather system parts: skill recommendations + tool descriptions
local recommendation = ""
local skill_count = 0
local rec_resp = orcs.request("skill::skill_manager", "recommend", {
intent = message,
context = history_context,
limit = 5,
})
if rec_resp and rec_resp.success and rec_resp.data then
local skills = rec_resp.data
-- Note: lua.to_value() (mlua serde) may place array elements in
-- the hash part of the table, causing # to return 0.
-- Use skills[1] existence check instead of #skills > 0.
if type(skills) == "table" and skills[1] ~= nil then
local lines = {}
for _, s in ipairs(skills) do
skill_count = skill_count + 1
local line = "- **" .. (s.name or "?") .. "**"
if s.description and s.description ~= "" then
line = line .. ": " .. s.description
end
lines[#lines + 1] = line
end
recommendation = "[System Recommendation]\n"
.. "The following skills are relevant to this task. "
.. "Consider using them to assist the user:\n"
.. table.concat(lines, "\n")
-- Register recommended skills as IntentDefs for tool-use resolution
local registered_names = {}
for _, s in ipairs(skills) do
local reg = orcs.register_intent({
name = s.name,
description = (s.description or "") .. " [Skill: invoke to retrieve full instructions]",
component = "skill::skill_manager",
operation = "execute",
params = {
name = {
type = "string",
description = "Name of the skill to execute",
required = true,
},
},
})
if reg and reg.ok then
registered_names[#registered_names + 1] = s.name
orcs.log("debug", _name .. ": registered skill intent: " .. s.name)
else
local err_msg = (reg and reg.error) or (reg and tostring(reg)) or "nil returned"
orcs.log("warn", _name .. ": skill intent registration failed: " .. s.name
.. " (" .. err_msg .. ")")
end
end
if #registered_names > 0 then
orcs.log("info", string.format(
"%s: registered %d skill intent(s): [%s]",
_name, #registered_names, table.concat(registered_names, ", ")
))
elseif skill_count > 0 then
orcs.log("warn", string.format(
"%s: all %d skill intent registration(s) failed",
_name, skill_count
))
end
end
end
-- Register static IntentDefs (delegate_task + agent intents) once per VM.
-- These definitions are fixed after init and don't change across LLM turns.
-- Skill IntentDefs (above) are NOT guarded because recommended skills vary per turn.
if not _intents_registered then
-- Register delegate_task intent: allows LLM to delegate work to a sub-agent.
-- The IntentDef routes to agent_mgr, which spawns/dispatches to delegate-worker.
local delegate_reg = orcs.register_intent({
name = "delegate_task",
description = "Delegate a task to an independent sub-agent that runs its own LLM session with tool access. "
.. "Use when the task requires separate investigation, research, or multi-step work "
.. "that would benefit from independent processing. The sub-agent works asynchronously; "
.. "results appear in your context on the next turn.",
component = "builtin::agent_mgr",
operation = "delegate",
timeout_ms = delegate_timeout_ms,
params = {
description = {
type = "string",
description = "Detailed description of the task to delegate",
required = true,
},
context = {
type = "string",
description = "Relevant context for the sub-agent (file paths, constraints, background)",
required = false,
},
},
})
if delegate_reg and delegate_reg.ok then
orcs.log("debug", _name .. ": registered delegate_task intent")
else
orcs.log("warn", _name .. ": delegate_task intent registration failed: "
.. ((delegate_reg and delegate_reg.error) or "unknown"))
end
-- Register IntentDefs for registered agents (from payload).
-- Allows LLM to invoke specialized agents as tools.
-- Routes to agent_mgr "invoke_agent" operation, which spawns on-demand.
local registered_agent_names = {}
for _, agent in ipairs(input.registered_agents or {}) do
local agent_name = agent.name or ""
if agent_name ~= "" then
local agent_reg = orcs.register_intent({
name = "invoke_" .. agent_name,
description = (agent.expertise ~= "" and agent.expertise)
or ("Invoke the " .. agent_name .. " agent"),
component = "builtin::agent_mgr",
operation = "invoke_agent",
timeout_ms = delegate_timeout_ms,
params = {
agent_name = {
type = "string",
description = "Name of the agent to invoke",
required = true,
},
message = {
type = "string",
description = "Task or message to send to the agent",
required = true,
},
},
})
if agent_reg and agent_reg.ok then
registered_agent_names[#registered_agent_names + 1] = agent_name
else
orcs.log("warn", _name .. ": agent intent registration failed: " .. agent_name
.. " (" .. ((agent_reg and agent_reg.error) or "unknown") .. ")")
end
end
end
if #registered_agent_names > 0 then
orcs.log("info", string.format(
"%s: registered %d agent intent(s): [%s]",
_name, #registered_agent_names, table.concat(registered_agent_names, ", ")
))
end
_intents_registered = true
end
local tool_desc = ""
if orcs.tool_descriptions then
local td = orcs.tool_descriptions()
if td and td ~= "" then
tool_desc = "## Available ORCS Tools\n" .. td
end
end
-- 2. Compose system block (skills + tool descriptions)
local system_parts = {}
if recommendation ~= "" then
system_parts[#system_parts + 1] = recommendation
end
if tool_desc ~= "" then
system_parts[#system_parts + 1] = tool_desc
end
local system_full = table.concat(system_parts, "\n\n")
-- 3. Compose history block
local history_block = ""
if history_context ~= "" then
history_block = "## Recent Conversation\n" .. history_context
end
-- 3b. Compose delegation results block (from completed sub-agent tasks)
local delegation_block = ""
if delegation_context ~= "" then
delegation_block = delegation_context
end
-- 4. Assemble prompt based on placement strategy
--
-- Fixed positions:
-- f_system → always at top (identity/core rules)
-- expertise → after f_system (agent identity)
-- console_block → after expertise (workspace context)
-- f_task → before history (project context)
-- f_guard → just before user message (output constraints)
--
-- Placement strategy controls skill/tool block (system_full) position only.
local sections = {}
-- Foundation:system — always top
if f_system ~= "" then sections[#sections + 1] = f_system end
-- Agent expertise — defines agent identity (injected via _agent_config)
local expertise = _agent_config.expertise or ""
if expertise ~= "" then
sections[#sections + 1] = "## Expertise\n" .. expertise
end
-- Console metrics — after agent identity
if console_block ~= "" then sections[#sections + 1] = console_block end
if placement == "top" then
-- [f:system] [Metrics] [Skills/Tools] [f:task] [History] [Delegation] [f:guard] [UserInput]
if system_full ~= "" then sections[#sections + 1] = system_full end
if f_task ~= "" then sections[#sections + 1] = f_task end
if history_block ~= "" then sections[#sections + 1] = history_block end
if delegation_block ~= "" then sections[#sections + 1] = delegation_block end
if f_guard ~= "" then sections[#sections + 1] = f_guard end
sections[#sections + 1] = message
elseif placement == "bottom" then
-- [f:system] [Metrics] [f:task] [History] [Delegation] [f:guard] [UserInput] [Skills/Tools]
if f_task ~= "" then sections[#sections + 1] = f_task end
if history_block ~= "" then sections[#sections + 1] = history_block end
if delegation_block ~= "" then sections[#sections + 1] = delegation_block end
if f_guard ~= "" then sections[#sections + 1] = f_guard end
sections[#sections + 1] = message
if system_full ~= "" then sections[#sections + 1] = system_full end
else
-- "both" (default):
-- [f:system] [Metrics] [Skills/Tools] [f:task] [History] [Delegation] [Skills/Tools] [f:guard] [UserInput]
if system_full ~= "" then sections[#sections + 1] = system_full end
if f_task ~= "" then sections[#sections + 1] = f_task end
if history_block ~= "" then sections[#sections + 1] = history_block end
if delegation_block ~= "" then sections[#sections + 1] = delegation_block end
if system_full ~= "" then sections[#sections + 1] = system_full end
if f_guard ~= "" then sections[#sections + 1] = f_guard end
sections[#sections + 1] = message
end
local prompt = table.concat(sections, "\n\n")
orcs.log("debug", string.format(
"%s: prompt built (placement=%s, skills=%d, history=%d, tools=%d, foundation=%d+%d+%d, metrics=%d, expertise=%d chars)",
_name, placement, skill_count, #history_context, #tool_desc,
#f_system, #f_task, #f_guard, #console_block, #expertise
))
-- 5. Call LLM via orcs.llm() with provider/model from config
-- Note: session_id is handled by the early-return path above;
-- this path is always a fresh first call.
local llm_opts = build_llm_opts(input)
-- Enable tool-use auto-resolution: LLM tool_use calls (skills, builtins)
-- are dispatched via IntentRegistry and results fed back automatically.
llm_opts.resolve = true
llm_opts.hil_intents = true -- Propagate Suspended for HIL approval
-- Apply _agent_config.llm overrides (agent-specific LLM settings).
-- Unconditional overwrite: keys in _agent_config.llm are explicitly
-- specified by the user (config.toml agents.<name>.llm_*), so they
-- take priority over the parent agent_mgr settings.
--
-- NOTE: This is static config-time override only. If a future feature
-- allows the Mgr to dynamically switch models at runtime (e.g. "this
-- task is simple, use Sonnet 4.5 instead"), that path MUST go through
-- HIL (Human-in-the-Loop) approval before overwriting agent config.
if _agent_config.llm then
for k, v in pairs(_agent_config.llm) do
llm_opts[k] = v
end
end
local llm_resp = orcs.llm(prompt, llm_opts)
if llm_resp and llm_resp.ok then
emit_success(message, llm_resp)
return {
success = true,
data = {
response = llm_resp.content,
session_id = llm_resp.session_id,
num_turns = llm_resp.num_turns,
cost = llm_resp.cost,
source = _name,
},
}
else
local err = (llm_resp and llm_resp.error) or "llm call failed"
orcs.output_with_level("[" .. _name .. "] Error: " .. tostring(err), "error")
return {
success = false,
error = err,
}
end
end,
on_signal = function(signal)
if signal.kind == "Veto" then
return "Abort"
end
return "Handled"
end,
}
]]
local agent_registry = {}
local spawned_agents = {}
local spawned_by_name = {}
local function deep_copy(t)
if type(t) ~= "table" then return t end
local copy = {}
for k, v in pairs(t) do
copy[k] = deep_copy(v)
end
return copy
end
local function register_agent(name, config)
if not name or name == "" then
return false, "agent name is required"
end
if agent_registry[name] then
return false, "duplicate agent registration: " .. name
end
config.name = name
agent_registry[name] = config
orcs.log("info", "registered agent '" .. name .. "'")
return true
end
local function find_spawned_by_name(name)
local ch_id = spawned_by_name[name]
if ch_id then return spawned_agents[ch_id] end
return nil
end
local function spawn_agent(config, opts)
if not config or not config.name then
return nil, "config.name is required"
end
if opts then
for k, v in pairs(opts) do
if config[k] == nil then
config[k] = v
end
end
end
local result = orcs.spawn_runner({
script = common_agent_script,
id = config.name,
globals = { _agent_config = config },
})
if not result then
return nil, "spawn_runner returned nil for agent '" .. config.name .. "'"
end
if result.ok then
local ch_id = result.channel_id
spawned_agents[ch_id] = {
name = config.name,
channel_id = ch_id,
fqn = result.fqn,
config = config,
persistent = config.persistent or false,
}
spawned_by_name[config.name] = ch_id orcs.log("info", string.format(
"spawned agent '%s' (channel=%s, fqn=%s)", config.name, ch_id, result.fqn
))
end
return result, (not result.ok) and result.error or nil
end
local function spawn_registered_agent(name)
local reg = agent_registry[name]
if not reg then
return nil, "agent not registered: " .. name
end
local existing = find_spawned_by_name(name)
if existing then
return { ok = true, fqn = existing.fqn }
end
local config = deep_copy(reg)
return spawn_agent(config)
end
local function list_registered_agents()
local result = {}
for name, config in pairs(agent_registry) do
result[#result + 1] = {
name = name,
expertise = config.expertise or "",
has_llm_override = config.llm ~= nil,
spawned = find_spawned_by_name(name) ~= nil,
}
end
table.sort(result, function(a, b) return a.name < b.name end)
return result
end
local function list_spawned_agents()
local result = {}
for ch_id, info in pairs(spawned_agents) do
result[#result + 1] = {
channel_id = ch_id,
name = info.name,
fqn = info.fqn,
persistent = info.persistent,
}
end
table.sort(result, function(a, b)
if a.name ~= b.name then return a.name < b.name end
return a.channel_id < b.channel_id
end)
return result
end
local HISTORY_LIMIT = 10 local MAX_AGENT_INTENTS = 3 local DEFAULT_DELEGATE_TIMEOUT_MS = 600000 local DEFAULT_CONCIERGE_TIMEOUT_MS = 600000 local DEFAULT_PING_TIMEOUT_MS = 5000
local delegate_timeout_ms = DEFAULT_DELEGATE_TIMEOUT_MS
local concierge_timeout_ms = DEFAULT_CONCIERGE_TIMEOUT_MS
local ping_timeout_ms = DEFAULT_PING_TIMEOUT_MS
local component_settings = {}
local concierge_fqn = nil
local delegate_worker_fqn = nil
local delegation_results = {}
local DELEGATION_RESULTS_LIMIT = 5
local delegation_counter = 0
local restart_counts = {} local MAX_RESTARTS = 3
local RESTART_WINDOW_SECS = 60
local function check_restart_allowed(fqn)
local now = os.time()
local entry = restart_counts[fqn]
if not entry or (now - entry.window_start) > RESTART_WINDOW_SECS then
restart_counts[fqn] = { count = 1, window_start = now }
return true
end
entry.count = entry.count + 1
if entry.count > MAX_RESTARTS then
orcs.log("error", string.format(
"AgentMgr: restart intensity exceeded for %s (%d/%d in %ds)",
fqn, entry.count, MAX_RESTARTS, RESTART_WINDOW_SECS
))
return false
end
return true
end
local function attempt_restart_concierge(old_fqn)
local check_fqn = old_fqn or concierge_fqn or "builtin::concierge"
if not check_restart_allowed(check_fqn) then
return false
end
local result = orcs.spawn_runner({
builtin = "concierge.lua",
globals = {
_delegate_timeout_ms = delegate_timeout_ms,
_concierge_timeout_ms = concierge_timeout_ms,
},
})
if result and result.ok then
concierge_fqn = result.fqn
orcs.log("info", "AgentMgr: concierge restarted as " .. concierge_fqn)
return true
end
orcs.log("error", "AgentMgr: concierge restart failed: " .. (result and result.error or "unknown"))
return false
end
local function attempt_restart_delegate_worker(old_fqn)
local check_fqn = old_fqn or delegate_worker_fqn or "builtin::delegate-worker"
if not check_restart_allowed(check_fqn) then
return false
end
local result = orcs.spawn_runner({
builtin = "delegate_worker.lua",
globals = { _delegate_timeout_ms = delegate_timeout_ms },
})
if result and result.ok then
delegate_worker_fqn = result.fqn
orcs.log("info", "AgentMgr: delegate-worker restarted as " .. delegate_worker_fqn)
return true
end
orcs.log("error", "AgentMgr: delegate-worker restart failed: " .. (result and result.error or "unknown"))
return false
end
local VALID_PLACEMENTS = { top = true, both = true, bottom = true }
local intent_allowed_agents = {}
local LLM_KEY_MAP = {
llm_provider = "provider",
llm_model = "model",
llm_base_url = "base_url",
llm_api_key = "api_key",
llm_temperature = "temperature",
llm_max_tokens = "max_tokens",
llm_timeout = "timeout",
llm_max_tool_turns = "max_tool_turns",
}
local function extract_llm_config(keys)
local config = {}
local map = keys or LLM_KEY_MAP
for src_key, dst_key in pairs(map) do
if component_settings[src_key] ~= nil then
config[dst_key] = component_settings[src_key]
end
end
return config
end
local routes = {
shell = { target = "builtin::shell", dispatch = "passthrough" },
skill = { target = "skill::skill_manager", dispatch = "operation" },
profile = { target = "profile::profile_manager", dispatch = "passthrough" },
tool = { target = "builtin::tool", dispatch = "passthrough" },
foundation = { target = "foundation::foundation_manager", dispatch = "operation" },
}
local function parse_route(message)
local prefix, rest = message:match("^@([%w_%-]+)%s+(.+)$")
if prefix then
return prefix:lower(), rest
end
local bare = message:match("^@([%w_%-]+)%s*$")
if bare then
return bare:lower(), ""
end
return nil, message
end
local function dispatch_route(route, body)
local operation, payload
if route.dispatch == "passthrough" then
operation = "input"
payload = { message = body }
else
local op, args = body:match("^(%S+)%s+(.+)$")
if op then
operation = op:lower()
payload = { message = args, name = args }
else
operation = body ~= "" and body:lower() or "status"
payload = {}
end
end
local resp = orcs.request(route.target, operation, payload)
if resp and resp.success then
if route.dispatch ~= "passthrough" then
local data = resp.data
if type(data) == "table" then
data = orcs.json_encode(data)
end
orcs.output(tostring(data or "ok"))
end
orcs.emit_event("Extension", "route_response", {
target = route.target,
operation = operation,
message = body,
})
return {
success = true,
data = {
response = resp.data,
source = route.target,
},
}
else
local err = (resp and resp.error) or "request failed"
orcs.output("[AgentMgr] @" .. route.target .. " error: " .. err, "error")
return { success = false, error = err }
end
end
local function utf8_truncate(s, max_bytes)
if #s <= max_bytes then return s end
local pos = max_bytes
while pos > 0 do
local b = string.byte(s, pos)
if b < 0x80 or b >= 0xC0 then break end
pos = pos - 1
end
if pos > 0 then
local b = string.byte(s, pos)
local char_len = 1
if b >= 0xF0 then char_len = 4
elseif b >= 0xE0 then char_len = 3
elseif b >= 0xC0 then char_len = 2
end
if pos + char_len - 1 > max_bytes then
return s:sub(1, pos - 1)
end
return s:sub(1, pos + char_len - 1)
end
return ""
end
local function fetch_history_context()
if not orcs.board_recent then
return ""
end
local ok, entries = pcall(orcs.board_recent, HISTORY_LIMIT)
orcs.log("debug", "board_recent returned " .. (ok and tostring(#(entries or {})) or "error") .. " entries")
if not ok or not entries or #entries == 0 then
return ""
end
local lines = {}
for _, entry in ipairs(entries) do
local payload = entry.payload or {}
local text = payload.message or payload.content or payload.response
if text and type(text) == "string" and text ~= "" then
local raw_src = entry.source
local src
if type(raw_src) == "table" then
src = raw_src.name or raw_src.namespace or "unknown"
else
src = tostring(raw_src or "unknown")
end
lines[#lines + 1] = string.format("- [%s] %s", src, utf8_truncate(text, 200))
end
end
if #lines > 0 then
return table.concat(lines, "\n")
end
return ""
end
local function fetch_delegation_context()
if #delegation_results == 0 then
return ""
end
local lines = {}
for _, r in ipairs(delegation_results) do
local status = r.success and "completed" or "failed"
local summary = utf8_truncate(r.summary or "", 500)
lines[#lines + 1] = string.format("- [%s] (%s) %s", r.request_id, status, summary)
end
return "## Delegation Results\n"
.. "The following tasks were delegated to sub-agents and have completed:\n"
.. table.concat(lines, "\n")
end
local function dispatch_llm(message)
if not concierge_fqn then
orcs.output_with_level("[AgentMgr] Error: no LLM backend available (concierge not initialized)", "error")
return { success = false, error = "no LLM backend available" }
end
if orcs.is_alive and not orcs.is_alive(concierge_fqn) then
orcs.log("error", "concierge '" .. concierge_fqn .. "' channel is closed (runner stopped)")
orcs.output_with_level(
"[AgentMgr] concierge '" .. concierge_fqn
.. "' is no longer running. Waiting for automatic restart...",
"warn"
)
return { success = false, error = "concierge became unreachable (restart pending)" }
end
local history_context = fetch_history_context()
local delegation_context = fetch_delegation_context()
local placement = component_settings.prompt_placement or "both"
if not VALID_PLACEMENTS[placement] then
orcs.log("warn", "Invalid prompt_placement '" .. placement .. "', falling back to both")
placement = "both"
end
local llm_config = extract_llm_config()
local registered_agents_for_payload = {}
intent_allowed_agents = {} local reg_list = list_registered_agents()
for i = 1, math.min(#reg_list, MAX_AGENT_INTENTS) do
registered_agents_for_payload[i] = reg_list[i]
intent_allowed_agents[reg_list[i].name] = true
end
local payload = {
message = message,
prompt_placement = placement,
llm_config = llm_config,
history_context = history_context,
delegation_context = delegation_context,
registered_agents = registered_agents_for_payload,
}
local delivered = orcs.emit_event("AgentTask", "process", payload)
if not delivered then
orcs.output_with_level("[AgentMgr] Error: AgentTask event was not delivered to any channel", "error")
return { success = false, error = "AgentTask event delivery failed" }
end
orcs.log("debug", string.format(
"dispatch_llm: emitted AgentTask event (message=%d chars)",
#message
))
return {
success = true,
data = {
dispatched = true,
message = message,
source = "event:AgentTask",
},
}
end
return {
id = "agent_mgr",
namespace = "builtin",
subscriptions = {"UserInput", "DelegateResult", "Lifecycle"},
output_to_io = true,
elevated = true,
child_spawner = true,
on_request = function(request)
local operation = request.operation or "input"
if operation == "completed" then
local payload = request.payload or {}
local request_id = payload.request_id
if request_id then
delegation_results[#delegation_results + 1] = {
request_id = request_id,
summary = payload.summary or payload.error or "",
success = payload.success or false,
cost = payload.cost,
timestamp = os.time(),
}
while #delegation_results > DELEGATION_RESULTS_LIMIT do
table.remove(delegation_results, 1)
end
orcs.log("info", string.format(
"AgentMgr: delegation %s %s (stored, %d results buffered)",
request_id,
payload.success and "completed" or "failed",
#delegation_results
))
if payload.success then
orcs.output("[AgentMgr] Delegate " .. request_id .. " completed.")
else
orcs.output_with_level(
"[AgentMgr] Delegate " .. request_id .. " failed: "
.. (payload.error or "unknown"),
"error"
)
end
local status = payload.success and "completed" or "failed"
dispatch_llm("[Delegate " .. request_id .. " " .. status
.. "] Review the delegation result and briefly report to the user.")
end
return { success = true }
end
if operation == "runner_exited" then
local payload = request.payload or {}
local fqn = payload.component_fqn or "unknown"
local reason = payload.exit_reason or "unknown"
orcs.log("warn", string.format(
"AgentMgr: runner exited: %s (reason=%s)", fqn, reason
))
if fqn == concierge_fqn then
local old_fqn = concierge_fqn
concierge_fqn = nil
if old_fqn:match("^builtin::") then
orcs.output_with_level(
"[AgentMgr] Concierge exited (" .. reason .. "). Attempting restart...",
"warn"
)
if attempt_restart_concierge(old_fqn) then
orcs.output("[AgentMgr] Concierge restarted successfully.")
else
orcs.output_with_level(
"[AgentMgr] Concierge restart failed. LLM processing unavailable.",
"error"
)
end
else
orcs.output_with_level(
"[AgentMgr] External concierge '" .. old_fqn
.. "' exited (" .. reason .. "). LLM processing unavailable.",
"error"
)
end
elseif fqn == delegate_worker_fqn then
local old_fqn = delegate_worker_fqn
delegate_worker_fqn = nil
orcs.output_with_level(
"[AgentMgr] Delegate-worker exited (" .. reason .. "). Attempting restart...",
"warn"
)
if attempt_restart_delegate_worker(old_fqn) then
orcs.output("[AgentMgr] Delegate-worker restarted successfully.")
else
orcs.output_with_level(
"[AgentMgr] Delegate-worker restart failed. Shared delegation unavailable.",
"error"
)
end
elseif fqn and fqn:match("^builtin::delegate%-") then
local request_id = fqn:match("^builtin::delegate%-(.+)$")
if request_id then
delegation_results[#delegation_results + 1] = {
request_id = request_id,
summary = "Worker exited: " .. reason,
success = false,
timestamp = os.time(),
}
while #delegation_results > DELEGATION_RESULTS_LIMIT do
table.remove(delegation_results, 1)
end
orcs.output_with_level(
"[AgentMgr] Delegate " .. request_id .. " worker exited: " .. reason,
"error"
)
end
else
orcs.log("info", string.format(
"AgentMgr: component exited (not managed): %s (%s)", fqn, reason
))
end
return { success = true }
end
if request.category == "Lifecycle" then
return { success = true }
end
if operation == "list_active" then
local agents = {}
agents.concierge_fqn = concierge_fqn
agents.delegate_fqn = delegate_worker_fqn
local concierge_cfg = component_settings.concierge
if concierge_cfg == "" then concierge_cfg = nil end
if not concierge_cfg then
agents.llm_provider = component_settings.llm_provider
agents.llm_model = component_settings.llm_model
end
agents.delegation_count = delegation_counter
agents.delegation_completed = #delegation_results
return { success = true, data = agents }
end
if operation == "delegate" then
local payload = request.payload or {}
local description = payload.description or ""
if description == "" then
return { success = false, error = "delegate_task requires a description" }
end
delegation_counter = delegation_counter + 1
local request_id = string.format("d%03d", delegation_counter)
local llm_config = extract_llm_config()
local delegate_backend = component_settings.delegate_backend
if delegate_backend == "" then delegate_backend = nil end
local task_payload = {
request_id = request_id,
description = description,
context = payload.context or "",
llm_config = llm_config,
delegate_backend = delegate_backend,
}
local worker = orcs.spawn_runner({
builtin = "delegate_worker.lua",
id = "delegate-" .. request_id,
globals = {
_delegate_payload = task_payload,
_delegate_timeout_ms = delegate_timeout_ms,
},
})
if not worker or not worker.ok then
local spawn_err = (worker and worker.error) or "unknown"
orcs.output_with_level(
"[AgentMgr] Error: failed to spawn delegate worker for " .. request_id,
"error"
)
return { success = false, error = "failed to spawn delegate worker: " .. spawn_err }
end
local event_kind = "DelegateTask-" .. request_id
local delivered = orcs.emit_event(event_kind, "process", task_payload)
if not delivered then
orcs.output_with_level(
"[AgentMgr] Error: DelegateTask event not delivered to worker " .. request_id,
"error"
)
return { success = false, error = "DelegateTask event delivery failed" }
end
orcs.log("info", string.format(
"AgentMgr: delegated task %s to dedicated worker (fqn=%s, %d chars)",
request_id, worker.fqn, #description
))
return {
success = true,
data = {
request_id = request_id,
worker_fqn = worker.fqn,
message = "Task delegated to sub-agent (id: " .. request_id .. "). Results will appear in your context on the next turn.",
},
}
end
if operation == "invoke_agent" then
local payload = request.payload or {}
local agent_name = payload.agent_name or ""
local agent_message = payload.message or ""
if agent_name == "" then
return { success = false, error = "invoke_agent requires agent_name" }
end
if not intent_allowed_agents[agent_name] then
orcs.log("warn", "invoke_agent: rejected unauthorized agent_name '" .. agent_name .. "'")
return { success = false, error = "agent '" .. agent_name .. "' is not authorized for LLM invocation" }
end
if agent_message == "" then
return { success = false, error = "invoke_agent requires message" }
end
local spawn_result, spawn_err = spawn_registered_agent(agent_name)
if not spawn_result or not spawn_result.ok then
return { success = false, error = spawn_err or "agent spawn failed" }
end
local agent_info = find_spawned_by_name(agent_name)
if not agent_info then
return { success = false, error = "agent spawned but not tracked" }
end
local rpc_timeout = (component_settings.llm_timeout or 120) * 1000
local resp = orcs.request(agent_info.fqn, "process", {
message = agent_message,
llm_config = extract_llm_config(),
prompt_placement = component_settings.prompt_placement or "both",
}, { timeout_ms = rpc_timeout })
if resp and resp.success then
return {
success = true,
data = {
response = resp.data,
source = "agent:" .. agent_name,
},
}
else
local err = (resp and resp.error) or "agent request failed"
return { success = false, error = err }
end
end
if operation == "list_agents" then
return {
success = true,
data = {
registered = list_registered_agents(),
spawned = list_spawned_agents(),
},
}
end
local message = request.payload
if type(message) == "table" then
message = message.message or message.content or ""
end
if type(message) ~= "string" or message == "" then
return { success = false, error = "empty message" }
end
orcs.log("info", "AgentMgr received: " .. utf8_truncate(message, 50))
local prefix, body = parse_route(message)
if prefix then
local route = routes[prefix]
if route then
orcs.log("info", "AgentMgr routing @" .. prefix .. " -> " .. route.target)
return dispatch_route(route, body)
end
local agent_info = find_spawned_by_name(prefix)
if not agent_info and agent_registry[prefix] then
orcs.log("info", "AgentMgr: on-demand spawn for @" .. prefix)
local spawn_result, spawn_err = spawn_registered_agent(prefix)
if spawn_result and spawn_result.ok then
agent_info = find_spawned_by_name(prefix)
else
orcs.output_with_level(
"[AgentMgr] @" .. prefix .. " spawn failed: " .. (spawn_err or "unknown"),
"error"
)
return { success = false, error = spawn_err or "agent spawn failed" }
end
end
if agent_info then
orcs.log("info", "AgentMgr routing @" .. prefix .. " -> " .. agent_info.fqn)
local rpc_timeout = (component_settings.llm_timeout or 120) * 1000
local resp = orcs.request(agent_info.fqn, "process", {
message = body,
llm_config = extract_llm_config(),
prompt_placement = component_settings.prompt_placement or "both",
}, { timeout_ms = rpc_timeout })
if resp and resp.success then
return {
success = true,
data = {
response = resp.data,
source = "agent:" .. prefix,
},
}
else
local err = (resp and resp.error) or "agent request failed"
orcs.output_with_level("[AgentMgr] @" .. prefix .. " error: " .. err, "error")
return { success = false, error = err }
end
end
orcs.log("debug", "AgentMgr: unknown prefix @" .. prefix .. ", falling through to concierge")
end
return dispatch_llm(message)
end,
on_signal = function(signal)
if signal.kind == "Veto" then
return "Abort"
end
return "Ignored"
end,
init = function(cfg)
if cfg and type(cfg) == "table" then
if next(component_settings) ~= nil then
orcs.log("warn", "agent_mgr: re-initialization detected, overwriting previous settings")
end
component_settings = cfg
orcs.log("debug", "agent_mgr: config received: " .. orcs.json_encode(cfg))
local g = cfg._global
if g and type(g) == "table" and g.timeouts and type(g.timeouts) == "table" then
if g.timeouts.delegate_ms then
delegate_timeout_ms = g.timeouts.delegate_ms
end
if g.timeouts.concierge_ms then
concierge_timeout_ms = g.timeouts.concierge_ms
end
end
if cfg.ping_timeout_ms then
ping_timeout_ms = cfg.ping_timeout_ms
end
end
local concierge = component_settings.concierge
if concierge == "" then concierge = nil end
local placement = component_settings.prompt_placement or "both"
local llm_provider = component_settings.llm_provider or "(default)"
local llm_model = component_settings.llm_model or "(default)"
orcs.log("info", string.format(
"agent_mgr initializing (concierge=%s, prompt_placement=%s, llm=%s/%s)...",
concierge or "off", placement, llm_provider, llm_model
))
if not concierge then
local result = orcs.spawn_runner({
builtin = "concierge.lua",
globals = {
_delegate_timeout_ms = delegate_timeout_ms,
_concierge_timeout_ms = concierge_timeout_ms,
},
})
if result.ok then
concierge_fqn = result.fqn
orcs.log("info", "spawned concierge agent (fqn=" .. concierge_fqn .. ")")
local ping_ok, ping_err = pcall(function()
local ping_config = extract_llm_config({
llm_provider = "provider",
llm_model = "model",
llm_base_url = "base_url",
llm_api_key = "api_key",
})
local ping_result = orcs.request(concierge_fqn, "ping", {
llm_config = ping_config,
})
if ping_result and ping_result.success and ping_result.data then
local d = ping_result.data
orcs.log("info", string.format(
"LLM provider ready: %s @ %s (status=%s, latency=%dms)",
d.provider or "?", d.base_url or "?",
tostring(d.status or "?"), d.latency_ms or 0
))
else
local err = (ping_result and ping_result.data and ping_result.data.error)
or (ping_result and ping_result.error)
or "unknown"
local kind = (ping_result and ping_result.data and ping_result.data.error_kind)
or "unknown"
orcs.log("warn", string.format(
"LLM provider unreachable: %s/%s (%s: %s)",
component_settings.llm_provider or "ollama",
component_settings.llm_model or "(default)",
kind, err
))
end
end)
if not ping_ok then
orcs.log("warn", "LLM health check failed: " .. tostring(ping_err))
end
else
orcs.log("error", "failed to spawn concierge: " .. (result.error or ""))
end
else
orcs.log("info", "concierge='" .. concierge .. "': verifying external agent...")
local probe_ok, probe_err = pcall(function()
local resp = orcs.request(concierge, "ping", {}, { timeout_ms = ping_timeout_ms })
if resp and resp.success then
concierge_fqn = concierge
orcs.log("info", "concierge='" .. concierge .. "': external agent verified")
else
local err_msg = (resp and resp.error) or "no response"
orcs.log("error", string.format(
"concierge='%s': external agent unreachable (%s). "
.. "LLM dispatch will be disabled until a valid concierge is available.",
concierge, err_msg
))
orcs.output_with_level(
"[AgentMgr] external concierge '" .. concierge
.. "' is not responding. Check config or component status.",
"warn"
)
end
end)
if not probe_ok then
orcs.log("error", "concierge probe failed: " .. tostring(probe_err))
orcs.output_with_level(
"[AgentMgr] external concierge '" .. concierge
.. "' probe threw an error. LLM dispatch disabled.",
"warn"
)
end
end
local delegate = orcs.spawn_runner({
builtin = "delegate_worker.lua",
globals = { _delegate_timeout_ms = delegate_timeout_ms },
})
if delegate.ok then
delegate_worker_fqn = delegate.fqn
orcs.log("info", "spawned delegate-worker agent (fqn=" .. delegate_worker_fqn .. ")")
else
orcs.log("warn", "failed to spawn delegate-worker: " .. (delegate.error or ""))
end
local agents_registered, agents_failed = 0, 0
local agents_config = component_settings.agents
if agents_config and type(agents_config) == "table" then
for name, agent_cfg in pairs(agents_config) do
if type(agent_cfg) == "table" then
local reg_cfg = {}
if agent_cfg.expertise then
reg_cfg.expertise = tostring(agent_cfg.expertise)
end
if agent_cfg.subscriptions then
reg_cfg.subscriptions = agent_cfg.subscriptions
end
local llm_overrides = {}
local has_llm = false
for _, key in ipairs({"llm_provider", "llm_model", "llm_base_url", "llm_api_key"}) do
if agent_cfg[key] then
llm_overrides[key:sub(5)] = agent_cfg[key]
has_llm = true
end
end
if has_llm then
reg_cfg.llm = llm_overrides
end
local ok, reg_err = register_agent(name, reg_cfg)
if ok then
agents_registered = agents_registered + 1
else
agents_failed = agents_failed + 1
orcs.log("warn", "agent registration failed: " .. name
.. " (" .. (reg_err or "unknown") .. ")")
end
else
agents_failed = agents_failed + 1
orcs.log("warn", "agent config invalid: " .. name
.. " (expected table, got " .. type(agent_cfg) .. ")")
end
end
end
if agents_registered > 0 or agents_failed > 0 then
orcs.log("info", string.format(
"config-based agents: %d registered, %d failed", agents_registered, agents_failed
))
end
if orcs.hook then
local ok, err = pcall(function()
orcs.hook("builtin::agent_mgr:request.post_dispatch", function(ctx)
local result = ctx.result
if result and type(result) == "table" then
local source = (result.data and result.data.source) or "unknown"
local status = result.success and "ok" or "fail"
orcs.log("info", string.format(
"[hook:routing] source=%s status=%s", source, status
))
end
return ctx
end)
end)
if ok then
orcs.log("info", "registered routing observability hook")
else
orcs.log("warn", "failed to register hook: " .. tostring(err))
end
end
local backend = concierge_fqn or "failed"
local delegate_status = delegate_worker_fqn and "ok" or "off"
local agents_status = agents_registered > 0 and tostring(agents_registered) or "none"
orcs.output("[AgentMgr] Ready (backend: " .. backend
.. ", delegate: " .. delegate_status
.. ", agents: " .. agents_status .. ")")
orcs.log("info", "agent_mgr initialized")
end,
shutdown = function()
orcs.log("info", "agent_mgr shutdown")
end,
}