docs/agents/custom-code-agent/building-blocks/typing-indicator.mdx
Use ctx.typing() to show a Thinking… or custom status while your handler runs. It posts immediately, like ctx.reply().
await ctx.typing('Searching the docs…'); // set or replace the status text
await ctx.typing(); // reset to the default "Thinking…"
await ctx.typing.stop(); // clear it for this turn
| Capability | Slack | Teams | Telegram | ||
|---|---|---|---|---|---|
| Live typing indicator | Yes (custom text) | Yes (custom text) | Yes (fixed) | Yes (custom text) | No |
| Eyes reaction as ack | Yes | Yes | Yes | Yes | Yes |
See Channels overview for the full matrix.
ctx.reply(), return a string or card from the handler, or return an AI SDK result that Novu maps to a reply. You do not need ctx.typing.stop() unless you want to clear the indicator without sending a message.onError suppresses the user-visible message.Before your handler runs, Novu shows a default liveness signal so users know the agent received their message:
This is controlled by Acknowledge incoming messages in the agent's Agent behavior settings in the dashboard. It is enabled by default.
If you use ctx.typing() with custom status text, consider turning this off to avoid a brief flicker when your status replaces the default indicator.
import { agent } from '@novu/framework';
export const myAgent = agent('my-agent', {
onMessage: async (message, ctx) => {
await ctx.typing('Looking that up…');
const answer = await lookup(message.text ?? '');
return answer;
},
});