2026-07-15-chat-agent-event-prompt-design.md 10 KB

ChatAgent Event Selection Prompt Design

Date: 2026-07-15 Status: approved for implementation planning

Context

In dual_agent mode, ChatAgent selects EventAgent capabilities by appending event names inside an <agent_events> block after its visible reply. The current generated prompt explains the catalog and output format, but treats event selection as optional and does not define when an event is required.

Recent local audit evidence shows the practical failure mode: ChatAgent says it will adjust volume or check weather, but emits no event. Examples include 声音调到90, 调大一点音量, and later weather requests. The model therefore produces a plausible conversational promise without causing the real action.

The generated prompt currently exists in two equivalent construction paths:

  • ToolRegistry.chat_event_system_message() supplies the runtime fallback for API clients that did not submit an EventPrompt.
  • buildAvailableEventsPrompt() generates the read-only EventPrompt shown and submitted by the browser console.

Both paths must retain the same behavioral contract. The text-event parser and the <agent_events> wire format are already stable and are not the source of the observed missed triggers.

Goals

  • Balance event recall against false positives.
  • Require an event whenever ChatAgent promises or claims a supported external action.
  • Trigger low-risk, read-only, or reversible capabilities from clear natural intent, even when the user does not phrase it as an imperative.
  • Ask one concise clarification before ambiguous or incomplete higher-impact actions.
  • Keep ordinary conversation, hypothetical discussion, unsupported requests, and capability questions event-free.
  • Preserve the existing event block protocol, parser, EventAgent argument resolution, event kernel, and invocation-mode boundaries.
  • Continue recognizing old generated EventPrompts when restoring sessions or workspace snapshots.

Non-goals

  • No separate intent-classification model call.
  • No provider-native tool schema changes.
  • No EventAgent argument protocol changes; ChatAgent still emits names only.
  • No event-kernel, handler, session, WebSocket, or active-turn behavior change.
  • No guarantee that every stochastic model follows the prompt perfectly; live evaluation measures adherence but does not replace deterministic contracts.

Approaches Considered

1. Decision-oriented prompt only

Replace the weak optional wording with explicit selection rules, consistency invariants, and compact positive and negative examples. Keep the current protocol and model-call count.

This is the selected approach because it directly addresses the observed failure, has the smallest runtime scope, and can be evaluated independently before introducing new architecture.

2. Metadata-driven trigger policies

Expose trigger and confirmation metadata through the event catalog and render event-specific policy dynamically. This scales better for a large heterogeneous registry, but requires domain, catalog API, frontend, and compatibility changes. It remains a possible follow-up if prompt-only evaluation shows that generic rules are insufficient.

3. Separate event-intent classifier

Run a dedicated classification step before ChatAgent response generation. This could improve isolation but adds latency, token cost, another failure mode, and coordination complexity. It is not justified before measuring the prompt-only approach.

Selected Prompt Contract

The generated EventPrompt will identify itself as protocol version 2 and use imperative rules. Its dynamic catalog remains name plus description only.

The prompt must communicate these rules:

  1. Decide whether the user's latest intent requires any available event.
  2. When a supported real-world action or fresh external-data request is clear, emit the matching event.
  3. If the visible reply says or implies that ChatAgent will perform, has performed, is checking, is changing, is scheduling, or is ending something, the same reply must append the corresponding event. ChatAgent must never promise a supported action without emitting its event.
  4. Low-risk, read-only, and reversible actions may be inferred from clear natural intent. 声音太小了 can select device.volume.adjust, and 明天天气怎么样 can select knowledge.web.search.
  5. For ambiguous or incomplete higher-impact actions, ask one concise clarification and emit no event yet. A complete and unambiguous request does not require redundant confirmation.
  6. Do not emit events for ordinary conversation, hypothetical statements, discussion about a capability, unsupported behavior, or a request that does not match an available event.
  7. Multiple independent clear intents may emit multiple exact event names, one per line.
  8. The event block is machine-control metadata, not part of the visible reply. It is allowed even when another prompt prohibits Markdown, lists, JSON, or other visible formatting.
  9. When no event is selected, omit the event block entirely.
  10. Never include parameters, explanations, bullets, code fences, or invented names inside the block.

The generated shape will remain:

Event selection protocol v2.
Available events:
- event.name: description
...
[decision rules and compact examples]
First write the user-facing reply normally. If one or more events are selected,
append exactly this block after the visible reply:
<agent_events>
event_name
</agent_events>
Use exact available event names only, one per line. Do not include parameters.

Decision Examples

The prompt will include a small, generic set of examples that match the current production-shaped capabilities without teaching argument extraction:

User intent Expected selection behavior
声音太小了 Reply naturally and emit device.volume.adjust.
声音调到90 Reply naturally and emit device.volume.adjust.
明天天气怎么样 Reply naturally and emit knowledge.web.search.
你回复太慢了 No event; response latency is not device volume.
你能调音量吗 No event; this asks about capability rather than requesting action.
提醒我开会 Ask for missing scheduling details and emit no event.
我明天下午三点要开会 No event; this is a statement unless the user requests scheduling.
A complete request to create a schedule Emit calendar.schedule.create.
An explicit goodbye or session-ending request Emit session.terminate.
Ordinary greeting or emotional conversation No event.

Examples are selection guidance only. EventAgent remains responsible for arguments and validation.

Data Flow and Compatibility

The browser continues to generate a read-only EventPrompt from selected tools. In dual_agent, exactly one managed EventPrompt is serialized. In chat_agent_tools, generated EventPrompt content remains excluded and provider tool schemas remain the only capability-selection surface.

The runtime continues to inject its registry-generated prompt only when no event instructions are already present. The Python and JavaScript prompt builders will use the same version marker, rule ordering, examples, catalog format, and output suffix.

isGeneratedEventPromptContent() must recognize both:

  • the legacy prefix You may request EventAgent work using this text protocol.;
  • the new Event selection protocol v2. prefix.

Recognition remains conservative: a known prefix alone is insufficient. The content must also contain the event block markers and the exact-name/no- parameters instruction. This preserves cleanup of historical generated prompts without deleting ordinary custom prompts that merely mention event syntax.

Verification Design

Implementation will use TDD.

Deterministic tests will first fail against the current prompt and then prove:

  • the backend prompt contains the version marker, mandatory action/event consistency rule, low-risk inference rule, higher-impact clarification rule, negative boundaries, exact output block, and compact examples;
  • the frontend prompt contains the same behavioral anchors and catalog output;
  • old and new generated EventPrompt signatures are both recognized;
  • ordinary custom prompts containing partial markers remain retained;
  • payload singleton and invocation-mode filtering behavior remain unchanged;
  • runtime fallback injection still supplies exactly one catalog and no provider tools in dual_agent;
  • parser behavior is unchanged.

Focused verification commands will cover the prompt/runtime tests and frontend source/behavior tests, followed by JavaScript syntax, the full suite, app import, and diff checks.

If a local live provider target and API key are available, run a fresh A/B evaluation with the same model and parameters. At minimum, evaluate the ten decision examples above across old and new prompts and record both missed required events and false positives. Existing historical SQLite sessions are evidence for the problem but must not be reused as an A/B input source because their accumulated context and prompt order differ.

Risks and Controls

  • Stronger rules may increase false positives. Negative examples and the capability-question/hypothetical boundaries control this risk.
  • Generic risk language may not scale to future events. If live evaluation exposes event-specific ambiguity, follow up with metadata-driven policy rather than continually expanding a monolithic prompt.
  • Prompt duplication between Python and JavaScript can drift. Tests assert the shared behavioral anchors and exact protocol suffix in both paths.
  • Historical snapshots may contain the old generated prompt. Dual-signature detection preserves deduplication and outbound singleton guarantees.
  • Other system prompts may prohibit visible formatting. The v2 prompt explicitly defines the event block as hidden machine metadata so those instructions do not suppress event emission.

Success Criteria

  • Direct or naturally expressed volume requests and fresh-data questions cause the matching event instead of an unsupported verbal promise.
  • Response-latency complaints, capability questions, ordinary chat, and incomplete scheduling requests do not produce unrelated events.
  • No protocol, parser, provider-tool mode, EventAgent argument, or event-kernel regression occurs.
  • Old and new EventPrompt snapshots remain safely deduplicated.
  • Deterministic verification passes, and any available live A/B evidence records both recall and false-positive outcomes rather than reporting only successful triggers.