Skip to content

Bug: ACP operational notices cannot be distinguished from assistant messages #1016

Description

@jask-aran

Issue details

Summary

In fx 0.0.10, fx acp sends both assistant reply text and operational notices as session/update agent_message_chunk events. Their messageId values differ, but the update does not identify which message is a notice. A client can separate the messages, but cannot classify them while they stream.

Steps to reproduce

  1. Start fx acp, initialize it, and create a session in a workspace where fx emits a context or skill notice.
  2. Send a short session/prompt, such as hi, and inspect the session/update notifications.
  3. Compare the live text with fx session --id <id> --json after the turn ends.

In our ACP client, a context notice and default appeared alongside Hi! What can I help you with?. The saved assistant reply contained only Hi! What can I help you with?. This is an observed client symptom; I have not attached a raw ACP trace.

Expected behavior

The live ACP stream identifies operational notices separately from assistant reply text. A client can show notices as activity and stream the reply into the answer. Model reasoning remains separate as agent_thought_chunk.

Actual behavior and impact

fx gives operational and assistant text different message IDs, but sends both through agent_message_chunk without a kind field. A client must show notices as assistant messages, delay the answer until it can read the saved session, or guess from message order or text. A different ID indicates a different message, not its purpose.

The distinction exists inside fx: assistant_source uses assistantMessageId(), while operational uses operationalMessageId(). Both paths call sendAgentText(), which writes an agent_message_chunk. pushReasoningDelta() already writes agent_thought_chunk.

Could fx send operational notices through a distinct, documented ACP-compatible signal, while reserving agent_message_chunk for assistant reply text? An advertised extension notification is one possible approach. This differs from #207, which addressed terminal-rendered text versus raw Markdown; the reply text streams here, but has no reliable notice discriminator.

Trace

Not attached. The example above contains no credentials or private paths.

Sensitive information

  • I reviewed the information above and removed secrets and other sensitive data.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions