Skip to content

feat(framework): improve agent framework DX and starter template fixes NV-7451#11003

Merged
ChmaraX merged 3 commits intonextfrom
nv-7451-improve-generated-starter-code-and-framework-dx
May 6, 2026
Merged

feat(framework): improve agent framework DX and starter template fixes NV-7451#11003
ChmaraX merged 3 commits intonextfrom
nv-7451-improve-generated-starter-code-and-framework-dx

Conversation

@ChmaraX
Copy link
Copy Markdown
Contributor

@ChmaraX ChmaraX commented May 6, 2026

Summary

  • Starter template (support-agent.tsx): removed onResolve, added inline comments explaining history/subscriber/metadata, personalised greeting with ctx.subscriber.firstName, added ctx.trigger() example in the resolution path
  • JSDoc (agent.types.ts): added documentation to all previously undocumented public interfaces — AgentHandlers, AgentContextBase properties, all four context subtypes, and all data shape interfaces
  • Handler signature redesign (breaking): all AgentHandlers callbacks now receive destructured payloads instead of a single ctx argument

Handler signature change

The single biggest change. Each handler now promotes its event-specific data to the top level:

// Before
onMessage: async (ctx) => { ctx.message.text; ctx.subscriber }
onAction:  async (ctx) => { const { actionId, value } = ctx.action!; }
onReaction:async (ctx) => { ctx.reaction.emoji }
onResolve: async (ctx) => { ctx.trigger(...) }

// After
onMessage: async ({ message, ctx }) => { message.text; ctx.subscriber }
onAction:  async ({ actionId, value, ctx }) => { /* no ctx.action!, no destructure */ }
onReaction:async ({ reaction, ctx }) => { reaction.emoji }
onResolve: async ({ ctx }) => { ctx.trigger(...) }

Why: actionId and value are accessed in virtually every onAction body — they shouldn't require two levels of nesting plus a non-null assertion. Applying the same pattern to all handlers keeps the API consistent: promoted fields = event-specific data that caused the handler to fire. ctx remains available for everything shared (subscriber, history, conversation, metadata, reply, trigger).

Breaking: package is in alpha (2.10.1-alpha.5), no deprecation wrapper added.

What's deferred (follow-up tickets)

Test plan

  • All 315 framework tests pass (pnpm test --run in packages/framework)
  • Starter template renders correctly — greeting uses subscriber name, LLM comment block is clean
  • Hover over ctx.subscriber, ctx.history, ctx.conversation.metadata in IDE — JSDoc appears
  • Hover over onMessage, onAction in AgentHandlers — per-handler docs appear

Made with Cursor

Summary by CodeRabbit

  • New Features

    • Agent handlers now receive event-specific payloads (destructured inputs) and richer event contexts for messages, actions, reactions, and resolves.
    • Starter agent example updated to use new signatures, personalized greetings, and a resolve flow.
  • Refactor

    • Internal event dispatch was reworked to route by event type and reply when handlers return content.
  • Documentation

    • Expanded JSDoc for agent types and contexts.
  • Tests

    • Unit/e2e tests updated to the new handler signatures.

…V-7451

- Rewrite starter template: remove onResolve, add inline comments explaining
  history/subscriber/metadata, show ctx.trigger in resolution path, use
  subscriber.firstName in greeting

- Add JSDoc to all undocumented public interfaces in agent.types.ts:
  AgentHandlers, AgentContextBase, AgentMessageContext, AgentActionContext,
  AgentReactionContext, AgentResolveContext, AgentMessage, AgentConversation,
  AgentSubscriber, AgentHistoryEntry, AgentAction, AgentReaction,
  AgentPlatformContext, AgentAttachment, AgentMessageAuthor

- Change all AgentHandlers signatures from (ctx) to destructured payloads:
  onMessage({ message, ctx }), onAction({ actionId, value, ctx }),
  onReaction({ reaction, ctx }), onResolve({ ctx })
  Promotes event-specific data to the top level; ctx still available for
  everything else. Breaking change — package is in alpha.

- Update handler.ts dispatch from uniform handlerMap to per-event switch,
  constructing the correct payload for each handler

- Update all 50 agent tests to use the new handler signatures

Co-authored-by: Cursor <cursoragent@cursor.com>
@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 6, 2026

@netlify
Copy link
Copy Markdown

netlify Bot commented May 6, 2026

Deploy Preview for dashboard-v2-novu-staging canceled.

Name Link
🔨 Latest commit fe5a61b
🔍 Latest deploy log https://app.netlify.com/projects/dashboard-v2-novu-staging/deploys/69fb44f148f5060008394db5

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 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: 1e797524-2cce-4087-8dfc-fc157b640dcb

📥 Commits

Reviewing files that changed from the base of the PR and between 8f0f0d4 and fe5a61b.

📒 Files selected for processing (1)
  • apps/api/src/app/agents/e2e/mock-agent-handler.ts

📝 Walkthrough

Walkthrough

Introduces payload-shaped agent handler signatures and event-specific AgentContext types; replaces handler-map dispatch with a switch over AgentEventEnum in runAgentHandler; expands agent types (messages, conversation, actions, reactions); updates runtime imports, tests, templates, and E2E mock handlers to the new shape.

Changes

Agent Event Handler Restructuring

Layer / File(s) Summary
Type System
packages/framework/src/resources/agent/agent.types.ts
Adds AgentMessageAuthor, AgentMessage, AgentConversation, AgentSubscriber, AgentHistoryEntry; extends AgentPlatformContext with isDM; augments AgentAction (value, sourceMessageId) and AgentReaction (message); introduces AgentMessageContext, AgentActionContext, AgentReactionContext, AgentResolveContext, union AgentContext; refactors AgentHandlers to payload-based signatures (onMessage({ message, ctx }), onAction({ actionId, value, ctx }), onReaction({ reaction, ctx }), onResolve({ ctx })).
Core Runtime / Wiring
packages/framework/src/handler.ts
Expands imports (AgentContextImpl, AgentDeliveryError, AgentEventEnum, utils, types); replaces handler-map dispatch with a switch on AgentEventEnum (ON_MESSAGE, ON_ACTION, ON_REACTION, ON_RESOLVE); constructs and passes the appropriate payload/context to each handler, conditionally invokes optional handlers, throws on unknown events, and replies when a handler returns non-null MessageContent.
Tests
packages/framework/src/resources/agent/agent.test.ts
Updates numerous tests to new payload/context signatures: handlers now destructure payloads ({ ctx }, { message, ctx }, { reaction, ctx }, { actionId, value, ctx }, { ctx } for resolve) while preserving original assertions and scenarios (ACKs, signals, file/card serialization, replies/edits).
Template Application
packages/novu/src/commands/init/templates/app-agent/.../support-agent.tsx
Updates scaffold agent to new handler signatures (onMessage: async ({ message, ctx }), onAction: async ({ actionId, value, ctx })), personalizes greeting from subscriber, adds conversation-resolve branch (calls ctx.resolve()), stores lastMessage metadata, and removes the onResolve implementation.
E2E Mock / Example
apps/api/src/app/agents/e2e/mock-agent-handler.ts
Adjusts mock handler lifecycle hooks to destructured payloads ({ message, ctx }, { actionId, value, ctx }, { ctx }) and adapts logging/message extraction accordingly.

Sequence Diagram

sequenceDiagram
    participant Trigger as Event Trigger
    participant Handler as runAgentHandler
    participant Switch as Event Switch
    participant Context as AgentContextImpl
    participant Hook as Agent Hook
    participant Reply as ctx.reply

    Trigger->>Handler: deliver AgentBridgeRequest (with event)
    Handler->>Switch: inspect AgentEventEnum

    alt ON_MESSAGE
        Switch->>Context: build AgentMessageContext
        Context->>Hook: invoke onMessage({ message, ctx })
        Hook->>Reply: returns MessageContent?
    else ON_ACTION
        Switch->>Context: build AgentActionContext
        Context->>Hook: invoke onAction({ actionId, value, ctx })
        Hook->>Reply: returns MessageContent?
    else ON_REACTION
        Switch->>Context: build AgentReactionContext
        Context->>Hook: invoke onReaction({ reaction, ctx })
        Hook->>Reply: returns MessageContent?
    else ON_RESOLVE
        Switch->>Context: build AgentResolveContext
        Context->>Hook: invoke onResolve({ ctx })
        Hook->>Reply: returns MessageContent?
    else Unknown
        Switch->>Handler: throw InvalidActionError
    end

    Handler->>Reply: if result != null then ctx.reply(result)
    Reply->>Handler: reply persisted / acknowledged
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • novuhq/novu#10974: Modifies agent typing to expose event-specific Agent*Context types and refactors runtime dispatch per AgentEventEnum.
  • novuhq/novu#10734: Updates agent handler runtime and template scaffolding to the same payload-based handler signatures used here.
  • novuhq/novu#10973: Adds sourceMessageId propagation on AgentAction, overlapping with the action-type changes in this PR.

Suggested reviewers

  • scopsy

"a rabbit hops to say hooray,
payloads now come a brighter way,
contexts split for every event,
replies sent back when handlers vent,
carrots and commits — celebrate the day! 🥕"

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main changes: improved agent framework DX and starter template fixes. It covers the primary objective of redesigning handler signatures and enhancing developer experience.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch nv-7451-improve-generated-starter-code-and-framework-dx

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

@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: 1

🧹 Nitpick comments (2)
packages/framework/src/handler.ts (1)

322-355: 💤 Low value

Defensive: non-null assertions on bridge fields can NPE on malformed events.

ctx.message!, ctx.action!, ctx.reaction! assume the bridge always sends the corresponding payload for each event. If a future bridge bug or replay sends an onAction event with action: null, ctx.action!.actionId throws an opaque TypeError instead of a structured AgentDeliveryError. Consider validating before dispatch and returning a typed error so the bridge can observe it via the existing error handling on Lines 236-242. Not strictly required since the bridge controls these payloads, but worth a quick guard given this is the public dispatch entry point.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/framework/src/handler.ts` around lines 322 - 355, Replace the unsafe
non-null assertions in the event dispatch switch (in handler.ts) by validating
bridge payloads before accessing them: check ctx.message, ctx.action, and
ctx.reaction exist when handling AgentEventEnum.ON_MESSAGE, ON_ACTION and
ON_REACTION respectively, and if any are missing throw/return a structured
AgentDeliveryError (including the event name and missing field) instead of
letting a raw TypeError surface; update the branches that call
registeredAgent.handlers.onMessage, onAction, onReaction (and onResolve guard)
to use these guards so the existing error handling path (the AgentDeliveryError
case used by the dispatch error handler) receives a typed error rather than an
opaque NPE.
packages/framework/src/resources/agent/agent.types.ts (1)

314-318: ⚡ Quick win

Make onAction payload consistent with onMessage/onReaction by passing the full AgentAction.

onMessage receives { message: AgentMessage, ctx } and onReaction receives { reaction: AgentReaction, ctx }, but onAction cherry-picks actionId and value from AgentAction and drops sourceMessageId. Developers who need sourceMessageId (e.g. to attach a reaction to the source card — see the test on lines 895-941 in agent.test.ts) must reach back into ctx.action.sourceMessageId, which defeats the purpose of the destructured payload and creates an inconsistent SDK surface.

Since the package is alpha and there's no deprecation contract yet, I'd lock in the consistent shape now.

♻️ Proposed signature change
-  onAction?: (payload: {
-    actionId: string;
-    value?: string;
-    ctx: AgentActionContext;
-  }) => Awaitable<MessageContent | void>;
+  onAction?: (payload: { action: AgentAction; ctx: AgentActionContext }) => Awaitable<MessageContent | void>;

This also requires the dispatch in packages/framework/src/handler.ts (Lines 329-337) to pass { action: ctx.action!, ctx: ... }, and the template/tests to destructure { action: { actionId, value }, ctx } (or { action, ctx }).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/framework/src/resources/agent/agent.types.ts` around lines 314 -
318, Change the onAction handler signature to accept the full AgentAction object
(make onAction?: (payload: { action: AgentAction; ctx: AgentActionContext }) =>
Awaitable<MessageContent | void>), so it matches onMessage/onReaction shapes;
update the dispatch that invokes onAction (where it currently passes { actionId,
value, ctx } or similar) to pass { action: ctx.action!, ctx } and update any
templates/tests to destructure either { action, ctx } or { action: { actionId,
value, sourceMessageId }, ctx } as needed. Ensure imports/type references for
AgentAction and AgentActionContext are present where onAction is declared and
where the handler dispatch occurs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/framework/src/handler.ts`:
- Around line 320-357: The variable result is read after the switch but may
remain unassigned if an optional handler like
registeredAgent.handlers.onAction/onReaction/onResolve is absent; initialize
result when declared (e.g., let result: MessageContent | void = undefined) so
TypeScript TS2454 is resolved and the intent of "no reply by default" is
explicit; update the declaration of result near the switch that branches on
AgentEventEnum and leave the rest of the handler logic unchanged.

---

Nitpick comments:
In `@packages/framework/src/handler.ts`:
- Around line 322-355: Replace the unsafe non-null assertions in the event
dispatch switch (in handler.ts) by validating bridge payloads before accessing
them: check ctx.message, ctx.action, and ctx.reaction exist when handling
AgentEventEnum.ON_MESSAGE, ON_ACTION and ON_REACTION respectively, and if any
are missing throw/return a structured AgentDeliveryError (including the event
name and missing field) instead of letting a raw TypeError surface; update the
branches that call registeredAgent.handlers.onMessage, onAction, onReaction (and
onResolve guard) to use these guards so the existing error handling path (the
AgentDeliveryError case used by the dispatch error handler) receives a typed
error rather than an opaque NPE.

In `@packages/framework/src/resources/agent/agent.types.ts`:
- Around line 314-318: Change the onAction handler signature to accept the full
AgentAction object (make onAction?: (payload: { action: AgentAction; ctx:
AgentActionContext }) => Awaitable<MessageContent | void>), so it matches
onMessage/onReaction shapes; update the dispatch that invokes onAction (where it
currently passes { actionId, value, ctx } or similar) to pass { action:
ctx.action!, ctx } and update any templates/tests to destructure either {
action, ctx } or { action: { actionId, value, sourceMessageId }, ctx } as
needed. Ensure imports/type references for AgentAction and AgentActionContext
are present where onAction is declared and where the handler dispatch occurs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8e48935f-04fc-4c96-91f9-2a9430f10e6e

📥 Commits

Reviewing files that changed from the base of the PR and between eda77fb and 09a431d.

📒 Files selected for processing (4)
  • packages/framework/src/handler.ts
  • packages/framework/src/resources/agent/agent.test.ts
  • packages/framework/src/resources/agent/agent.types.ts
  • packages/novu/src/commands/init/templates/app-agent/ts/app/novu/agents/support-agent.tsx

Comment thread packages/framework/src/handler.ts Outdated
@ChmaraX ChmaraX changed the title feat(shared): improve agent framework DX and starter template fixes NV-7451 feat(framework): improve agent framework DX and starter template fixes NV-7451 May 6, 2026
…d biome

Co-authored-by: Cursor <cursoragent@cursor.com>
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 6, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@novu/framework@11003
npm i https://pkg.pr.new/novu@11003

commit: fe5a61b

…er signatures

Co-authored-by: Cursor <cursoragent@cursor.com>
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: 1

🧹 Nitpick comments (1)
packages/framework/src/handler.ts (1)

327-359: 💤 Low value

Double cast ctx as unknown as AgentXxxContext signals a structural mismatch worth abstracting.

Each branch repeats ctx as unknown as AgentMessageContext | AgentActionContext | AgentReactionContext | AgentResolveContext. The unknown step is required because AgentContextImpl doesn't satisfy any of the narrowed event-specific context types directly, which both hides real type-safety regressions if those interfaces drift and adds noise.

Consider a small narrowing helper (or making AgentContextImpl implement each context interface conditionally) so the cast lives in one place and keeps unknown out of the dispatch site:

♻️ Example helper
const asMessageCtx = (c: AgentContextImpl): AgentMessageContext => c as unknown as AgentMessageContext;
const asActionCtx  = (c: AgentContextImpl): AgentActionContext  => c as unknown as AgentActionContext;
// ...etc

Then call sites become ctx: asMessageCtx(ctx), etc., keeping the unsafe cast isolated and easy to audit.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/framework/src/handler.ts` around lines 327 - 359, The repeated
double-casts (ctx as unknown as AgentMessageContext / AgentActionContext /
AgentReactionContext / AgentResolveContext) indicate a structural mismatch
between AgentContextImpl and the event-specific context interfaces; create a
small set of narrowing helpers (e.g., asMessageCtx, asActionCtx, asReactionCtx,
asResolveCtx) that accept AgentContextImpl and return the respective
AgentXxxContext by performing the cast in one place, then replace the inline
casts in the dispatch (the branches using
registeredAgent.handlers.onMessage/onAction/onReaction/onResolve) with calls
like ctx: asMessageCtx(ctx) etc., isolating the unsafe cast and making future
audits easier.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/framework/src/handler.ts`:
- Around line 326-360: The handlers dispatch currently uses non-null assertions
(ctx.message!, ctx.action!, ctx.reaction!) and may call
registeredAgent.handlers.onMessage/onAction/onReaction/onResolve with undefined
on malformed payloads; update the dispatch in the switch branches to validate
the required payload fields (e.g., ensure ctx.message exists for onMessage,
ctx.action and ctx.action.actionId for onAction, ctx.reaction for onReaction,
etc.) before calling replyIfPresent/handler, and if validation fails throw a
clear framework error (e.g., InvalidAgentEventPayload or InvalidActionError)
with a descriptive message so user handlers are never invoked with undefined.

---

Nitpick comments:
In `@packages/framework/src/handler.ts`:
- Around line 327-359: The repeated double-casts (ctx as unknown as
AgentMessageContext / AgentActionContext / AgentReactionContext /
AgentResolveContext) indicate a structural mismatch between AgentContextImpl and
the event-specific context interfaces; create a small set of narrowing helpers
(e.g., asMessageCtx, asActionCtx, asReactionCtx, asResolveCtx) that accept
AgentContextImpl and return the respective AgentXxxContext by performing the
cast in one place, then replace the inline casts in the dispatch (the branches
using registeredAgent.handlers.onMessage/onAction/onReaction/onResolve) with
calls like ctx: asMessageCtx(ctx) etc., isolating the unsafe cast and making
future audits easier.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: dfaf47f3-21b4-4348-8aa6-6db79867fab7

📥 Commits

Reviewing files that changed from the base of the PR and between 09a431d and 8f0f0d4.

📒 Files selected for processing (1)
  • packages/framework/src/handler.ts

Comment on lines +326 to +360
await replyIfPresent(
await registeredAgent.handlers.onMessage({
message: ctx.message!,
ctx: ctx as unknown as AgentMessageContext,
})
);
break;
case AgentEventEnum.ON_ACTION:
if (registeredAgent.handlers.onAction) {
await replyIfPresent(
await registeredAgent.handlers.onAction({
actionId: ctx.action!.actionId,
value: ctx.action!.value,
ctx: ctx as unknown as AgentActionContext,
})
);
}
break;
case AgentEventEnum.ON_REACTION:
if (registeredAgent.handlers.onReaction) {
await replyIfPresent(
await registeredAgent.handlers.onReaction({
reaction: ctx.reaction!,
ctx: ctx as unknown as AgentReactionContext,
})
);
}
break;
case AgentEventEnum.ON_RESOLVE:
if (registeredAgent.handlers.onResolve) {
await replyIfPresent(
await registeredAgent.handlers.onResolve({
ctx: ctx as unknown as AgentResolveContext,
})
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Non-null assertions on ctx.message / ctx.action / ctx.reaction may forward undefined to handlers on malformed payloads.

For each event branch, the corresponding field is forced with ! (Lines 328, 337-338, 348) and then handed to user code typed as required. If a request reaches AGENT_EVENT with event=onMessage but the body lacks message (or action.actionId / reaction for the other branches), the handler will be invoked with undefined despite the type promising otherwise, leading to confusing Cannot read properties of undefined errors inside user code rather than a clear framework-level rejection.

Consider validating presence before dispatch and throwing a descriptive error (e.g. via InvalidActionError or a dedicated agent error) so the contract between event name and payload shape is enforced at the boundary.

🛡️ Sketch of a guard at dispatch time
       case AgentEventEnum.ON_MESSAGE:
+        if (!ctx.message) {
+          throw new InvalidActionError(event, AgentEventEnum);
+        }
         await replyIfPresent(
           await registeredAgent.handlers.onMessage({
-            message: ctx.message!,
+            message: ctx.message,
             ctx: ctx as unknown as AgentMessageContext,
           })
         );
         break;

Apply the analogous guard to ON_ACTION (ctx.action), ON_REACTION (ctx.reaction), and ON_RESOLVE if it has any required fields.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/framework/src/handler.ts` around lines 326 - 360, The handlers
dispatch currently uses non-null assertions (ctx.message!, ctx.action!,
ctx.reaction!) and may call
registeredAgent.handlers.onMessage/onAction/onReaction/onResolve with undefined
on malformed payloads; update the dispatch in the switch branches to validate
the required payload fields (e.g., ensure ctx.message exists for onMessage,
ctx.action and ctx.action.actionId for onAction, ctx.reaction for onReaction,
etc.) before calling replyIfPresent/handler, and if validation fails throw a
clear framework error (e.g., InvalidAgentEventPayload or InvalidActionError)
with a descriptive message so user handlers are never invoked with undefined.

@ChmaraX ChmaraX merged commit 3b1b555 into next May 6, 2026
39 checks passed
@ChmaraX ChmaraX deleted the nv-7451-improve-generated-starter-code-and-framework-dx branch May 6, 2026 13:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant