Skip to content

Feature request: async query mode with completion notification for long-running tasks #153

@lygshanwj

Description

@lygshanwj

Feature Request: Async query mode with completion notification

Problem

Currently, ACP query is synchronous — the client (acpx) blocks until the agent (e.g., cursor-agent) returns the full response. For short tasks this works well, but for long-running tasks (5+ minutes), this creates issues:

  1. Session is blocked: The ACP session cannot process other queries while waiting
  2. Timeout risk: Long tasks may exceed the ttl (default 300s), causing the session to drop
  3. No intermediate status: The caller has no visibility into task progress
  4. Resource waste: The acpx process sits idle, holding an open stdio pipe, waiting for a response

This is especially painful when integrating with orchestrators like OpenClaw, where multiple tasks need to be dispatched and results collected asynchronously.

Proposed Solution: Async Query + Notification

Add an optional async mode to the query method, where the agent can acknowledge receipt immediately and deliver results later via a notification.

Flow

Client                              Agent
  |                                   |
  |-- query (async: true) ----------->|
  |<-- ack { taskId, status } --------|  (immediate, non-blocking)
  |                                   |
  |   (client is free to do other     |
  |    work or send more queries)     |
  |                                   |  (agent working...)
  |                                   |
  |<-- notification/taskComplete -----|  (when done)
  |    { taskId, result, status }     |
  |                                   |

Proposed Protocol Changes

1. Extended query params:

{
  "method": "query",
  "params": {
    "prompt": "Build a REST API with FastAPI...",
    "async": true  // NEW: request async execution
  }
}

2. Immediate acknowledgment response:

{
  "result": {
    "taskId": "task_abc123",
    "status": "accepted",
    "message": "Task accepted, will notify on completion"
  }
}

3. New notification method (agent → client):

{
  "method": "notification/taskComplete",
  "params": {
    "taskId": "task_abc123",
    "status": "completed",  // or "failed", "cancelled"
    "result": {
      "message": "Here is the full output..."
    }
  }
}

4. Optional: Progress notification:

{
  "method": "notification/taskProgress",
  "params": {
    "taskId": "task_abc123",
    "progress": 0.6,
    "message": "Running tests..."
  }
}

Capability negotiation

Agents that support async mode should declare it during initialize:

{
  "agentCapabilities": {
    "asyncQuery": true  // NEW
  }
}

If the agent doesn't support asyncQuery, acpx should fall back to the current synchronous behavior transparently.

Use Cases

  1. Long-running code generation: "Build a complete project with tests" — may take 10+ minutes
  2. Multi-agent orchestration: Dispatch tasks to multiple agents in parallel, collect results as they complete
  3. CI/CD-like workflows: Kick off a build/test task, get notified when done
  4. OpenClaw integration: The gateway dispatches a task via ACP and immediately frees the agent to handle other chat messages; when the result arrives, it pushes a notification to the user

Workarounds Today

  • Multiple concurrent sessions: Works but each session is still individually blocked
  • External hook scripts: Asking the agent to run a notification script at the end — unreliable, depends on agent compliance
  • Polling from orchestrator layer: Defeats the purpose of ACP's structured protocol

Compatibility

  • Fully backward-compatible: async param defaults to false, existing behavior unchanged
  • Agents that don't support it simply ignore the flag and respond synchronously
  • JSON-RPC already supports notifications (one-way messages), so no protocol-level changes needed

Related

  • This is complementary to session/load and session/new — async tasks would still belong to a session
  • Claude Code already has a similar pattern via lifecycle Hooks (Stop Hook / SessionEnd Hook), proving the async dispatch model works well in practice

Environment

  • acpx: 0.3.0
  • Observed with: cursor-agent (Cursor IDE CLI) via OpenClaw gateway
  • OS: Windows 10

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions