Skip to content

feat(runtime,kernel): non-blocking agent_send — extend the #4983 async-task tracker to inter-agent delegation #6043

Description

@DaBlitzStein

Problem

agent_send is synchronous-only: tool_agent_send (crates/librefang-runtime/src/tool_runner/agent.rs:94-111) awaits kh.send_to_agent_as(...), which runs the target agent's full loop and returns its final response as the tool result. That await is wrapped by the tool-execution timeout (tool_timeout_secs, default 120s), so any delegation that takes longer than the timeout always fails — and even within the budget it blocks the caller's loop, so a Telegram-facing agent goes unresponsive while it waits.

Real failure (production proteo)

deannatroi delegated a research task to agent Viajecinio via agent_send. Viajecinio's nested loop did legitimate multi-step web research (DuckDuckGo + page fetches + several deepseek-v4 turns) that ran past 120s, so deannatroi's agent_send was killed:

WARN run_agent_loop: Tool execution timed out after 120s  tool=agent_send  agent.name=deannatroi

From deannatroi's side the delegation simply "failed", even though Viajecinio was working fine. This is the exact class of failure that #4983 (async task tracker) was created to solve — but #4983 was only wired to workflows, never to agent_send.

What already exists (the template)

#4983 / its PR shipped a complete async-completion path that workflow_start already uses:

  • KernelHandle::start_workflow_async_tracked(workflow_id, input, caller_agent_id, caller_session_id) (crates/librefang-kernel-handle/src/workflow_runner.rs:283) — registers the run on the async-task tracker, spawns it detached, returns a run_id immediately.
  • On completion the kernel calls complete_async_task(...) (crates/librefang-kernel/src/kernel/task_registry.rs:257), which injects a TaskCompletionEvent back into the originating (agent, session)mid-turn (AgentLoopSignal::TaskCompleted, Feature: Implement message injection between tool calls #956 channel) if the loop is live, else wake-idle (spawns a fresh turn with a [System] [ASYNC_RESULT] message), with the trigger-lane + per-agent concurrency semaphores applied.

agent_send has no equivalent — there is no async variant and no register_async_task wiring.

Proposal

Extend the existing #4983 tracker to inter-agent delegation (no new transport needed — reuse register_async_task / complete_async_task):

  1. Add a non-blocking mode to agent_send — an async: bool param (default false, fully backward-compatible) on the existing tool, OR a sibling agent_start tool mirroring the workflow_run / workflow_start split. (Leaning toward the async param to avoid a confusing new tool name next to agent_spawn.)
  2. Add a KernelHandle method analogous to start_workflow_async_tracked (e.g. send_to_agent_async_tracked(agent_id, message, caller_agent_id, caller_session_id, conversation_key)) that registers a TaskKind for the delegation, spawns the callee loop detached, and on completion calls complete_async_task with the callee's response.
  3. Return a task_id immediately so the caller's LLM frees its turn; the reply arrives later via the existing mid-turn / wake-idle injection.
  4. Depth guard (AGENT_CALL_DEPTH, agent.rs:85-92) and taint checks stay; the async spawn must propagate the depth scope.

Acceptance

  • agent_send with async=true returns a task_id without blocking; the target's reply is injected back into the caller's session on completion (mid-turn and wake-idle both covered).
  • Blocking agent_send (default) is byte-for-byte unchanged.
  • A long (> tool_timeout_secs) delegation no longer hits the tool timeout in async mode.
  • Integration test mirroring async_task_tracker_runtime_test.rs but for an agent_send delegation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/kernelCore kernel (scheduling, RBAC, workflows)area/runtimeAgent loop, LLM drivers, WASM sandboxenhancementNew feature or requesthas-prA pull request has been linked to this issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions