Delegation And Zombie Contexts

Last updated: April 12, 2026

Assistant Delegation and Zombie Contexts

The assistant module supports complex multi-agent collaboration via delegation, allowing a primary agent to assign tasks to specialized sub-agents.

Delegation Mechanisms

1. Synchronous Delegation (call_agent)

The primary agent waits for the sub-agent to complete its task and provide a result within the same session. This is best for quick, direct sub-tasks.

2. Asynchronous Delegation (call_agent_async)

The primary agent assigns a task to a sub-agent and continues its own execution or ends its session. The result is delivered later via a notification. This is essential for long-running tasks.

Zombie Contexts

"Zombie Contexts" are a robust persistence mechanism designed to handle asynchronous results when the original (parent) session is no longer active (e.g., after a restart or session timeout).

How it Works

  1. Registration: When call_agent_async is invoked, the ZombieParentRegistry captures critical metadata about the parent session (ChatID, Platform, UserRole, AgentName).
  2. Execution: The sub-agent runs in a background goroutine.
  3. Completion: When the sub-agent finishes, the system checks if the parent session is still active.
  4. Fallback: If the parent session is gone, the system retrieves the "Zombie" metadata and uses it to send a persona-aware notification to the user (via WhatsApp or Discord) informing them of the result.

WhatsApp LID→JID Resolution Fix (April 2026)

Issue: WhatsApp async delegation notifications failed because LID (Login ID) format wasn't being resolved to JID (Jabber ID) format.

Example:

  • LID: 123456789 (phone number only)
  • JID: 123456789@s.whatsapp.net (full WhatsApp address format)

Fix: Implemented 3-tier fallback in resolveWhatsAppChatID:

Tier Check Action
1 Already JID format? Use directly
2 Phone number extractable? Append @s.whatsapp.net
3 Fallback Use stored ZombieParent ChatID

Files: assistant/planner.go, assistant/scheduler.go, assistant/wakeup.go

Empty ChatID Bug: ZombieParent registration could capture empty ChatID. Fixed with fallback to use stored parent ChatID when current is empty.

Sequence Diagram: Async Delegation & Zombie Recovery

sequenceDiagram
    participant N as Nikki (Parent)
    participant Z as Zombie Registry
    participant S as Sasha (Sub-Agent)
    participant W as WhatsApp Notifier

    N->>S: call_agent_async(task)
    N->>Z: RegisterZombieParent(ChatID, Meta)
    N-->>N: Session Ends/Saves
    Note over S: Sasha works on task...
    S->>S: Task Complete
    S->>Z: Retrieve Zombie Metadata
    Z-->>S: Meta (ChatID, User, etc.)
    S->>W: Send Notification ("Hey, Sasha here. I finished X...")

Key Files & Functions

  • assistant/planner.go: Contains AsyncCallAgent which initiates async delegation.
  • assistant/chat_persistence.go: Manages the storage and rehydration of ParentFacts.
  • NotifyUserAsyncComplete(): The fallback function that uses zombie contexts to deliver results.
  • kill_async_agent: A tool for manually terminating hanging sub-agents.

Guidance for AI Agents

  • Use Async for Long Tasks: If a task involves deep research or long-running scripts, use call_agent_async to avoid blocking the user.
  • Provide Task IDs: Always reference the unique Task ID in your initial delegation and final report.
  • Check Pending Tasks: Use list_pending_async_agents to see what your sub-agents are currently working on.

Cross-References