Skip to content

feat(ag-ui): add ACTIVITY_SNAPSHOT and ACTIVITY_DELTA event support#1137

Merged
omeraplak merged 3 commits intoVoltAgent:mainfrom
corners99:feat/ag-ui-activity-events
Mar 24, 2026
Merged

feat(ag-ui): add ACTIVITY_SNAPSHOT and ACTIVITY_DELTA event support#1137
omeraplak merged 3 commits intoVoltAgent:mainfrom
corners99:feat/ag-ui-activity-events

Conversation

@corners99
Copy link
Copy Markdown
Contributor

@corners99 corners99 commented Mar 6, 2026

Summary

Adds support for AG-UI ACTIVITY_SNAPSHOT and ACTIVITY_DELTA events to the @voltagent/ag-ui adapter. These event types are defined in @ag-ui/core but were not previously emitted by the VoltAgent adapter, making it impossible for frontends to receive structured activity messages from VoltAgent tools.

Use Case

We're building a real estate development platform that uses VoltAgent with an Angular frontend and A2UI (Google's Agent-to-UI protocol). Our agents need to emit interactive UI surfaces (forms, confirmation cards, pricing grids) to the frontend. Without activity event support, tool results containing UI payloads are only available as raw JSON strings in TOOL_CALL_RESULT events — there's no way to signal that the result should be rendered as interactive UI.

With this change, a VoltAgent tool can return:

return {
  activityType: "ui-surface",
  content: { surfaceId: "project-create", components: [...] }
};

And the adapter will emit an ACTIVITY_SNAPSHOT event that frontends can handle natively.

Changes

1. Tool result activity detection

When a tool-result stream part contains an object with { activityType: string, content: Record<string, any> }, the adapter emits an ACTIVITY_SNAPSHOT event in addition to the regular TOOL_CALL_RESULT (so the model's tool call is still properly resolved). Works with both single objects and arrays.

2. Explicit activity stream part handlers

Adds "activity-snapshot" and "activity-delta" cases to convertVoltStreamPartToEvents(). These handle custom stream part types that VoltAgent hooks or future core changes may emit.

3. Improved activity message round-tripping

Incoming activity role messages from the AG-UI client now preserve their activityType as a prefix when folded into VoltAgent messages, giving the model better context about prior activity state.

No Breaking Changes

  • Existing tool results without activityType are handled identically to before
  • The TOOL_CALL_RESULT event is always emitted for tool results (even when activity events are also emitted)
  • No changes to the public API surface

Test Plan

  • Tool returning { activityType: "test", content: { foo: "bar" } } emits both ACTIVITY_SNAPSHOT and TOOL_CALL_RESULT
  • Tool returning a plain object (no activityType) emits only TOOL_CALL_RESULT (no regression)
  • Tool returning an array of activity objects emits multiple ACTIVITY_SNAPSHOT events
  • Activity messages in AG-UI input preserve activityType in converted messages
  • Custom "activity-snapshot" stream parts emit ACTIVITY_SNAPSHOT events
  • Custom "activity-delta" stream parts emit ACTIVITY_DELTA events

🤖 Generated with Claude Code


Summary by cubic

Adds ACTIVITY_SNAPSHOT and ACTIVITY_DELTA support to the @voltagent/ag-ui adapter so tools can emit structured activity UI that frontends can render. No breaking changes; TOOL_CALL_RESULT is still emitted.

  • New Features

    • Emit ACTIVITY_SNAPSHOT when tool results include { activityType, content } (single or array; arrays can mix snapshots and deltas via patch).
    • Convert custom activity-snapshot and activity-delta stream parts into activity events (snapshots use replace, deltas use patch).
    • Preserve activityType when folding incoming AG‑UI activity messages into VoltAgent messages by prefixing it in assistant text.
  • Bug Fixes

    • Define activity event constants and types locally for @ag-ui/core v0.0.37 compatibility.
    • Handle activity-snapshot/activity-delta in the switch default via string checks and cast activity events to BaseEvent to resolve type errors.

Written for commit ad46281. Summary will update on new commits.

Summary by CodeRabbit

  • New Features

    • Support for activity signals (snapshot and delta) in VoltAgent integration.
    • Assistant text now includes an optional activity-type prefix for clearer context.
    • Activity data is extracted from tool results and emitted alongside original tool results so both are available downstream.
  • Chores

    • Added release metadata documenting the patch release.

The AG-UI adapter now converts activity-related stream parts and tool
results into proper AG-UI activity events, enabling frontends to render
rich interactive UI (e.g. A2UI surfaces, CopilotKit panels) from
VoltAgent tool results.

Changes:

1. Tool result activity detection — when a tool returns an object with
   `{ activityType, content }`, the adapter emits an ACTIVITY_SNAPSHOT
   event alongside the regular TOOL_CALL_RESULT. This lets tools signal
   that their output should be rendered as interactive UI rather than
   shown as raw JSON.

2. Explicit activity stream parts — adds handlers for custom
   "activity-snapshot" and "activity-delta" stream part types. These
   allow VoltAgent hooks or custom implementations to emit activity
   events directly into the AG-UI stream.

3. Improved activity message round-tripping — incoming activity messages
   from the AG-UI client now preserve their activityType when folded
   into the VoltAgent message format, giving the model better context
   about prior activity state.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 6, 2026

🦋 Changeset detected

Latest commit: ad46281

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@voltagent/ag-ui Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 6, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: eab2a602-eb03-4aa6-b842-7f101cab302a

📥 Commits

Reviewing files that changed from the base of the PR and between e4c2e4e and ad46281.

📒 Files selected for processing (1)
  • packages/ag-ui/src/voltagent-agent.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/ag-ui/src/voltagent-agent.ts

📝 Walkthrough

Walkthrough

This PR expands AG-UI integration to surface ACTIVITY_SNAPSHOT and ACTIVITY_DELTA events, detects activity structures inside tool-result payloads, emits activity events (while retaining original tool-result events), and adjusts assistant-message folding to prefix activity type when present.

Changes

Cohort / File(s) Summary
AG-UI activity handling
packages/ag-ui/src/voltagent-agent.ts
Introduce local ACTIVITY_SNAPSHOT / ACTIVITY_DELTA event types and TS shapes; update event emission typing; convert activity-snapshot/activity-delta stream-parts into activity events; detect activity payloads inside tool-result via tryExtractActivityFromToolResult and emit activity events alongside original TOOL_CALL_RESULT; fold activity content into assistant text with [Activity: <type>] prefix when applicable.
Release metadata
.changeset/slimy-yaks-talk.md
Add changeset marking a patch release for @voltagent/ag-ui to announce the activity-event additions.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant VoltAgent
  participant Tool
  participant AG_UI

  Client->>VoltAgent: send stream parts (text / tool-result / activity-snapshot / activity-delta)
  VoltAgent->>VoltAgent: inspect stream part type
  alt activity-snapshot / activity-delta
    VoltAgent->>AG_UI: emit ACTIVITY_SNAPSHOT / ACTIVITY_DELTA (messageId, activityType, content/patch, replace)
    VoltAgent->>Client: optionally fold activity into assistant text (prefix with [Activity: <type>])
  else tool-result
    VoltAgent->>Tool: forward or process tool-result
    Tool-->>VoltAgent: tool-result payload (object or array)
    VoltAgent->>VoltAgent: tryExtractActivityFromToolResult(tool-result)
    alt activity extracted
      VoltAgent->>AG_UI: emit ACTIVITY_* event(s)
      VoltAgent->>Client: emit original TOOL_CALL_RESULT as well
    else no activity
      VoltAgent->>Client: emit original TOOL_CALL_RESULT
    end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hop through streams with eager eyes,
I spot snapshots, deltas, tiny surprise.
I tag their types and gently relay,
Folding whispers into messages on my way. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main change: adding ACTIVITY_SNAPSHOT and ACTIVITY_DELTA event support to the ag-ui package.
Description check ✅ Passed The description comprehensively covers the PR objectives, use case, specific changes, breaking change assessment, and test plan, though the PR checklist items are incomplete.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/ag-ui/src/voltagent-agent.ts">

<violation number="1" location="packages/ag-ui/src/voltagent-agent.ts:599">
P2: Single-object tool results with `{ activityType, patch }` are not converted into `ACTIVITY_DELTA` events, creating an inconsistent API where deltas work for arrays but not single objects.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/ag-ui/src/voltagent-agent.ts`:
- Around line 600-606: The event construction for AGUIActivitySnapshotEvent is
generating a fresh messageId via generateId() which detaches single-object
activity results from their assistant message; change the messageId assignment
in the AGUIActivitySnapshotEvent creation (where EventType.ACTIVITY_SNAPSHOT is
set) to prefer (obj.messageId as string) if present, otherwise use the existing
fallbackMessageId variable instead of calling generateId(), so single-object {
activityType, content } results remain attached and behave like the array and
direct "activity-snapshot" paths.
- Around line 408-410: The shared union type VoltAgentTextStreamPart is missing
the "activity-snapshot" and "activity-delta" discriminants, causing callers to
cast to any and forcing `as string` workarounds; update the
VoltAgentTextStreamPart definition to include variants for "activity-snapshot"
and "activity-delta" (matching the runtime shapes handled in the switch cases
around lines 524 and 544) so callers can create those parts without type
assertions and the switch can use the literal discriminants directly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 083af77e-fc5b-4291-b120-bfab96f3fc3c

📥 Commits

Reviewing files that changed from the base of the PR and between 549fc45 and 28d90f8.

📒 Files selected for processing (1)
  • packages/ag-ui/src/voltagent-agent.ts

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
.changeset/slimy-yaks-talk.md (1)

5-5: Consider expanding the changeset description for CHANGELOG clarity.

Changeset descriptions become CHANGELOG entries read by package consumers. The current description is quite terse and doesn't explain what these new events provide or when they're emitted.

Consider expanding the description to help users understand the new functionality:

📝 Suggested enhanced description
-feat(ag-ui): add ACTIVITY_SNAPSHOT and ACTIVITY_DELTA event support
+feat(ag-ui): add ACTIVITY_SNAPSHOT and ACTIVITY_DELTA event support
+
+The AG-UI adapter now emits ACTIVITY_SNAPSHOT and ACTIVITY_DELTA events alongside existing events when:
+- Tool results contain activity objects with `activityType` and `content` fields
+- Stream parts explicitly specify "activity-snapshot" or "activity-delta" types
+
+This enables frontends to receive structured activity UI payloads while maintaining backward compatibility—existing TOOL_CALL_RESULT events are still emitted.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.changeset/slimy-yaks-talk.md at line 5, Update the changeset description
for the feat entry that mentions ACTIVITY_SNAPSHOT and ACTIVITY_DELTA: replace
the terse line with a short paragraph explaining what each event does (e.g.,
ACTIVITY_SNAPSHOT emits a full activity state snapshot, ACTIVITY_DELTA emits
incremental updates), when they are emitted (initial load vs. subsequent
changes), what key payload fields consumers can expect, and any migration or
compatibility notes for existing listeners so the CHANGELOG entry is actionable
for package users.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.changeset/slimy-yaks-talk.md:
- Line 5: Update the changeset description for the feat entry that mentions
ACTIVITY_SNAPSHOT and ACTIVITY_DELTA: replace the terse line with a short
paragraph explaining what each event does (e.g., ACTIVITY_SNAPSHOT emits a full
activity state snapshot, ACTIVITY_DELTA emits incremental updates), when they
are emitted (initial load vs. subsequent changes), what key payload fields
consumers can expect, and any migration or compatibility notes for existing
listeners so the CHANGELOG entry is actionable for package users.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0743e464-41c5-446f-a9e1-129cc943709c

📥 Commits

Reviewing files that changed from the base of the PR and between 28d90f8 and e4c2e4e.

📒 Files selected for processing (1)
  • .changeset/slimy-yaks-talk.md

@omeraplak
Copy link
Copy Markdown
Member

Hey @corners99,
Thank you so much 🔥 When you have a moment, could you check the build issues as well?

@ag-ui/core v0.0.37 does not export ActivitySnapshotEvent,
ActivityDeltaEvent, or ACTIVITY_SNAPSHOT/ACTIVITY_DELTA enum values.
Define these types locally until upstream adds them. Move
activity-snapshot/activity-delta handling from invalid `case` syntax
to the default block with string comparison. Cast activity events to
BaseEvent for subscriber.next() compatibility.

https://claude.ai/code/session_01EdPoo8p31C68M2kJmayj9J
@omeraplak omeraplak merged commit bb6e9b1 into VoltAgent:main Mar 24, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants