trigger-chat-agent-advanced
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesechat.agent: advanced and operational
chat.agent:高级可运行功能
chat.agentexternalIdchatIdsessionsAgentChatTwo namespaces are easy to confuse: the agent definition imports from
; Head Start / Node-listener server entries import from
.
chatchat@trigger.dev/sdk/aichat@trigger.dev/sdk/chat-serverchat.agentexternalIdchatIdsessionsAgentChat有两个命名空间容易混淆:代理定义从导入;Head Start/Node监听器服务入口从导入。
chat@trigger.dev/sdk/aichat@trigger.dev/sdk/chat-serverchatSetup
配置步骤
Happy path: drive an agent from server-side code (task, webhook, or script) with .
AgentChatts
import { AgentChat } from "@trigger.dev/sdk/chat";
import type { myAgent } from "./trigger/my-agent";
const chat = new AgentChat<typeof myAgent>({ agent: "my-chat", clientData: { userId: "user_123" } });
const stream = await chat.sendMessage("Review PR #42");
const text = await stream.text();
await chat.close();sendMessage()ChatStreamtext()result(){ text, toolCalls, toolResults }messages().streamsteer(text)stop()sendRaw(uiMessages)sendAction(action)preload()reconnect()常规路径:通过服务端代码(任务、Webhook或脚本)使用驱动代理。
AgentChatts
import { AgentChat } from "@trigger.dev/sdk/chat";
import type { myAgent } from "./trigger/my-agent";
const chat = new AgentChat<typeof myAgent>({ agent: "my-chat", clientData: { userId: "user_123" } });
const stream = await chat.sendMessage("Review PR #42");
const text = await stream.text();
await chat.close();sendMessage()ChatStreamtext()result(){ text, toolCalls, toolResults }messages().streamsteer(text)stop()sendRaw(uiMessages)sendAction(action)preload()reconnect()Core patterns
核心模式
1. Raw Sessions for non-chat, bi-directional I/O
1. 用于非聊天双向I/O的原始Sessions
Reach for directly when the chat abstraction does not fit: agent inboxes, approval flows,
server-to-server pipelines. is idempotent on ;
cannot start with .
sessionssessions.start(env, externalId)externalIdsession_ts
import { sessions } from "@trigger.dev/sdk";
const { id, publicAccessToken } = await sessions.start({
type: "chat.agent",
externalId: chatId,
taskIdentifier: "my-chat",
triggerConfig: { tags: [`chat:${chatId}`], basePayload: { chatId, trigger: "preload" } },
});
const session = sessions.open(chatId); // no network call; methods are lazy
await session.out.append({ kind: "message", text: "hello" });
const next = await session.in.once<MyEvent>({ timeoutMs: 30_000 });sessions.open(id).insendon(handler)peekwaittask.run()waitWithIdleTimeout.outappendpipewriterreadwriteControltrimTosessions.list({ type, tag, status, ... })for awaitsessions.updatesessions.close当聊天抽象不适用时,直接使用:代理收件箱、审批流程、服务端到服务端流水线。在上是幂等的;不能以开头。
sessionssessions.start(env, externalId)externalIdsession_ts
import { sessions } from "@trigger.dev/sdk";
const { id, publicAccessToken } = await sessions.start({
type: "chat.agent",
externalId: chatId,
taskIdentifier: "my-chat",
triggerConfig: { tags: [`chat:${chatId}`], basePayload: { chatId, trigger: "preload" } },
});
const session = sessions.open(chatId); // 无网络调用;方法为惰性执行
await session.out.append({ kind: "message", text: "hello" });
const next = await session.in.once<MyEvent>({ timeoutMs: 30_000 });sessions.open(id).insendon(handler)peekwaittask.run()waitWithIdleTimeout.outappendpipewriterreadwriteControltrimTosessions.list({ type, tag, status, ... })for awaitsessions.updatesessions.close2. Durable sub-agent as a streaming tool
2. 作为流工具的持久化子代理
AgentChattool()toModelOutputts
import { tool } from "ai";
import { AgentChat } from "@trigger.dev/sdk/chat";
import { z } from "zod";
const researchTool = tool({
description: "Delegate research to a specialist agent.",
inputSchema: z.object({ topic: z.string() }),
execute: async function* ({ topic }, { abortSignal }) {
const chat = new AgentChat({ agent: "research-agent" });
const stream = await chat.sendMessage(topic, { abortSignal });
yield* stream.messages(); // UIMessage snapshots become preliminary tool results
await chat.close();
},
toModelOutput: ({ output: message }) => {
const lastText = message?.parts?.findLast((p: { type: string }) => p.type === "text") as
| { text?: string }
| undefined;
return { type: "text", value: lastText?.text ?? "Done." };
},
});For a subtask exposed via , stream progress to the agent's run with
. accepts .
Inside the subtask, read context with and
().
execute: ai.toolExecute(task)chat.stream.writer({ target: "root" })target"self" | "parent" | "root" | <runId>ai.toolCallId()ai.chatContextOrThrow<typeof myChat>(){ chatId, turn, continuation, clientData }ts
import { chat, ai } from "@trigger.dev/sdk/ai";
const { waitUntilComplete } = chat.stream.writer({
target: "root",
execute: ({ write }) =>
write({ type: "data-research-status", id: partId, data: { query, status: "in-progress" } }),
});
await waitUntilComplete();AI SDK的内的会委托给持久化子代理;其响应会作为初步工具结果流式返回。为工具设置,让模型看到简洁的摘要。
tool()AgentChattoModelOutputts
import { tool } from "ai";
import { AgentChat } from "@trigger.dev/sdk/chat";
import { z } from "zod";
const researchTool = tool({
description: "Delegate research to a specialist agent.",
inputSchema: z.object({ topic: z.string() }),
execute: async function* ({ topic }, { abortSignal }) {
const chat = new AgentChat({ agent: "research-agent" });
const stream = await chat.sendMessage(topic, { abortSignal });
yield* stream.messages(); // UIMessage快照成为初步工具结果
await chat.close();
},
toModelOutput: ({ output: message }) => {
const lastText = message?.parts?.findLast((p: { type: string }) => p.type === "text") as
| { text?: string }
| undefined;
return { type: "text", value: lastText?.text ?? "Done." };
},
});对于通过暴露的子任务,使用将进度流式传输到代理的运行中。接受。在子任务内部,使用和读取上下文(返回)。
execute: ai.toolExecute(task)chat.stream.writer({ target: "root" })target"self" | "parent" | "root" | <runId>ai.toolCallId()ai.chatContextOrThrow<typeof myChat>(){ chatId, turn, continuation, clientData }ts
import { chat, ai } from "@trigger.dev/sdk/ai";
const { waitUntilComplete } = chat.stream.writer({
target: "root",
execute: ({ write }) =>
write({ type: "data-research-status", id: partId, data: { query, status: "in-progress" } }),
});
await waitUntilComplete();3. Background injection: defer + inject
3. 后台注入:defer + inject
chat.defer(promise)onTurnCompletechat.inject(messages)ModelMessage[]prepareStepts
export const myChat = chat.agent({
id: "my-chat",
onTurnComplete: async ({ messages }) => {
chat.defer(
(async () => {
const analysis = await analyzeConversation(messages);
chat.inject([{ role: "system", content: `[Analysis]\n\n${analysis}` }]);
})()
);
},
run: async ({ messages, signal }) =>
streamText({ ...chat.toStreamTextOptions({ registry }), messages, abortSignal: signal, stopWhen: stepCountIs(15) }),
});chat.defer(promise)onTurnCompletechat.inject(messages)ModelMessage[]prepareStepts
export const myChat = chat.agent({
id: "my-chat",
onTurnComplete: async ({ messages }) => {
chat.defer(
(async () => {
const analysis = await analyzeConversation(messages);
chat.inject([{ role: "system", content: `[Analysis]\n\n${analysis}` }]);
})()
);
},
run: async ({ messages, signal }) =>
streamText({ ...chat.toStreamTextOptions({ registry }), messages, abortSignal: signal, stopWhen: stepCountIs(15) }),
});4. Compaction (threshold-based)
4. 压缩(基于阈值)
compaction.shouldCompactsummarizecompactUIMessagesprepareStepchat.toStreamTextOptions()prepareStepts
compaction: {
shouldCompact: ({ totalTokens }) => (totalTokens ?? 0) > 80_000,
summarize: async ({ messages }) =>
(await generateText({
model: anthropic("claude-haiku-4-5"),
messages: [...messages, { role: "user", content: "Summarize concisely." }],
})).text,
},compaction.shouldCompactsummarizecompactUIMessagesprepareStepchat.toStreamTextOptions()prepareStepts
compaction: {
shouldCompact: ({ totalTokens }) => (totalTokens ?? 0) > 80_000,
summarize: async ({ messages }) =>
(await generateText({
model: anthropic("claude-haiku-4-5"),
messages: [...messages, { role: "user", content: "Summarize concisely." }],
})).text,
},5. Actions: mutate state without a turn
5. 动作:无需轮次即可修改状态
actionSchemaonActionchat.historyslicereplacerollbackToremovegetPendingToolCallsextractNewToolResultshydrateMessagesonActionrun()StreamTextResultUIMessagets
export const myChat = chat.agent({
id: "my-chat",
actionSchema: z.discriminatedUnion("type", [
z.object({ type: z.literal("undo") }),
z.object({ type: z.literal("rollback"), targetMessageId: z.string() }),
]),
onAction: async ({ action }) => {
if (action.type === "undo") chat.history.slice(0, -2);
if (action.type === "rollback") chat.history.rollbackTo(action.targetMessageId);
},
run: async ({ messages, signal }) => streamText({ model: anthropic("claude-sonnet-4-5"), messages, abortSignal: signal }),
});Send from the browser with , or server-side with
.
transport.sendAction(chatId, { type: "undo" })agentChat.sendAction({ type: "rollback", targetMessageId: "msg-3" })actionSchemaonActionchat.historyslicereplacerollbackToremovegetPendingToolCallsextractNewToolResultshydrateMessagesonActionrun()StreamTextResultUIMessagets
export const myChat = chat.agent({
id: "my-chat",
actionSchema: z.discriminatedUnion("type", [
z.object({ type: z.literal("undo") }),
z.object({ type: z.literal("rollback"), targetMessageId: z.string() }),
]),
onAction: async ({ action }) => {
if (action.type === "undo") chat.history.slice(0, -2);
if (action.type === "rollback") chat.history.rollbackTo(action.targetMessageId);
},
run: async ({ messages, signal }) => streamText({ model: anthropic("claude-sonnet-4-5"), messages, abortSignal: signal }),
});在浏览器中通过发送动作,或在服务端通过发送。
transport.sendAction(chatId, { type: "undo" })agentChat.sendAction({ type: "rollback", targetMessageId: "msg-3" })6. Fast starts: Head Start
6. 快速启动:Head Start
chat.headStart@trigger.dev/sdk/chat-server/aiaizodts
import { chat } from "@trigger.dev/sdk/chat-server";
import { streamText, stepCountIs } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { headStartTools } from "@/lib/chat-tools/schemas";
export const chatHandler = chat.headStart({
agentId: "my-chat",
run: async ({ chat: helper }) =>
streamText({
...helper.toStreamTextOptions({ tools: headStartTools }),
model: anthropic("claude-sonnet-4-6"),
system: "You are helpful.",
stopWhen: stepCountIs(15),
}),
});
// Next.js: export const POST = chatHandler; Transport: headStart: "/api/chat"Node-only frameworks wrap a Web Fetch handler with . Use the same
model on both sides to avoid a tone shift between turn 1 and turn 2+.
chat.toNodeListener(handler)chat.headStart@trigger.dev/sdk/chat-server/aiaizodts
import { chat } from "@trigger.dev/sdk/chat-server";
import { streamText, stepCountIs } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { headStartTools } from "@/lib/chat-tools/schemas";
export const chatHandler = chat.headStart({
agentId: "my-chat",
run: async ({ chat: helper }) =>
streamText({
...helper.toStreamTextOptions({ tools: headStartTools }),
model: anthropic("claude-sonnet-4-6"),
system: "You are helpful.",
stopWhen: stepCountIs(15),
}),
});
// Next.js: export const POST = chatHandler; Transport: headStart: "/api/chat"仅支持Node的框架使用包装Web Fetch处理器。在两侧使用相同的模型,以避免第一轮和第二轮及以后的语气差异。
chat.toNodeListener(handler)7. chat.local: init in onBoot, not onChatStart
7. chat.local:在onBoot中初始化,而非onChatStart
chat.local<T>({ id })onBootonChatStartts
const userContext = chat.local<{ name: string; plan: "free" | "pro" }>({ id: "userContext" });
export const myChat = chat.agent({
id: "my-chat",
onBoot: async ({ clientData }) => userContext.init({ name: "Alice", plan: "pro" }),
run: async ({ messages, signal }) => streamText({ /* ... */ }),
});chat.local<T>({ id })onBootonChatStartts
const userContext = chat.local<{ name: string; plan: "free" | "pro" }>({ id: "userContext" });
export const myChat = chat.agent({
id: "my-chat",
onBoot: async ({ clientData }) => userContext.init({ name: "Alice", plan: "pro" }),
run: async ({ messages, signal }) => streamText({ /* ... */ }),
});8. Pending messages (mid-stream user input)
8. 待处理消息(流中用户输入)
A message sent while a turn is streaming should NOT cancel the stream. Configure
(, , , ) on the agent so the SDK's
auto-injected folds them in at the next boundary. On the frontend,
returns , , , and ; send via
.
pendingMessagesshouldInjectprepareonReceivedonInjectedprepareStepusePendingMessagespendingsteer(text)queue(text)promoteToSteering(id)transport.sendPendingMessage(chatId, uiMessage, metadata?)在轮次流式传输时发送的消息不应取消流。在代理上配置(包含、、、),以便SDK自动注入的在下一个边界处将其合并。在前端,返回、、和;通过发送。
pendingMessagesshouldInjectprepareonReceivedonInjectedprepareStepusePendingMessagespendingsteer(text)queue(text)promoteToSteering(id)transport.sendPendingMessage(chatId, uiMessage, metadata?)9. Recovery and version upgrades
9. 恢复与版本升级
onRecoveryBootchat.requestUpgrade()chat.requestUpgrade()onTurnStartonValidateMessagesrun()run()chat.defer()currentRunIdclientDatats
const SUPPORTED_VERSIONS = new Set(["v2", "v3"]);
onTurnStart: async ({ clientData }) => {
if (clientData?.protocolVersion && !SUPPORTED_VERSIONS.has(clientData.protocolVersion)) {
chat.requestUpgrade();
}
},For OOM resilience, set (and ) on the agent so retries land on a larger preset.
oomMachinemachineonRecoveryBootchat.requestUpgrade()chat.requestUpgrade()onTurnStartonValidateMessagesrun()run()chat.defer()currentRunIdclientDatats
const SUPPORTED_VERSIONS = new Set(["v2", "v3"]);
onTurnStart: async ({ clientData }) => {
if (clientData?.protocolVersion && !SUPPORTED_VERSIONS.has(clientData.protocolVersion)) {
chat.requestUpgrade();
}
},为了提升OOM恢复能力,在代理上设置(和),以便重试时使用更大的预设配置。
oomMachinemachine10. Offline testing with mockChatAgent
10. 使用mockChatAgent进行离线测试
@trigger.dev/sdk/ai/testsendMessagesendRegeneratesendActionsendStopsendHeadStartsendHandoverseedSnapshotseedSessionOutTailseedSessionOutPartialseedSessionInTailturn.chunksharness.allChunksts
import { mockChatAgent } from "@trigger.dev/sdk/ai/test"; // BEFORE the agent module
import { myChatAgent } from "./my-chat.js";
const harness = mockChatAgent(myChatAgent, { chatId: "test-1", clientData: { model } });
try {
const turn = await harness.sendMessage({ id: "u1", role: "user", parts: [{ type: "text", text: "hi" }] });
// assert against turn.chunks
} finally {
await harness.close();
}Options include (),
, , , , , and . Set
to simulate an OOM-retry attempt. drives a
non-chat task offline.
mode"preload" | "submit-message" | "handover-prepare" | "continuation"preloadcontinuationpreviousRunIdsnapshottaskContextsetupLocalstaskContext.ctx.attempt.number > 1runInMockTaskContext@trigger.dev/sdk/ai/testsendMessagesendRegeneratesendActionsendStopsendHeadStartsendHandoverseedSnapshotseedSessionOutTailseedSessionOutPartialseedSessionInTailturn.chunksharness.allChunksts
import { mockChatAgent } from "@trigger.dev/sdk/ai/test"; // 必须在代理模块之前导入
import { myChatAgent } from "./my-chat.js";
const harness = mockChatAgent(myChatAgent, { chatId: "test-1", clientData: { model } });
try {
const turn = await harness.sendMessage({ id: "u1", role: "user", parts: [{ type: "text", text: "hi" }] });
// 断言turn.chunks
} finally {
await harness.close();
}选项包括()、、、、、和。设置以模拟OOM重试尝试。驱动非聊天任务的离线测试。
mode"preload" | "submit-message" | "handover-prepare" | "continuation"preloadcontinuationpreviousRunIdsnapshottaskContextsetupLocalstaskContext.ctx.attempt.number > 1runInMockTaskContext11. Custom transport: the wire protocol
11. 自定义传输层:有线协议
Endpoints: (create), (SSE),
, . is
. The
carries , (), , , , ,
, and more. Control records are header-form: (with
optional , ) and . The
TS helpers and (documented in
) handle batch decoding and control-record filtering for you.
POST /api/v1/sessionsGET /realtime/v1/sessions/{id}/outPOST /realtime/v1/sessions/{id}/in/appendPOST /api/v1/sessions/{id}/closeChatInputChunk{ kind: "message"; payload: ChatTaskWirePayload } | { kind: "stop"; message? }ChatTaskWirePayloadchatIdtriggersubmit-message | regenerate-message | preload | close | action | handover-preparemessage?metadata?action?continuation?previousRunId?trigger-control: turn-completepublic-access-tokensession-in-event-idtrigger-control: upgrade-requiredSSEStreamSubscriptioncontrolSubtype(headers)docs/ai-chat/client-protocol.mdx端点:(创建)、(SSE)、、。的格式为。包含、()、、、、、等。控制记录为头部格式:(可选包含、)和。TS辅助工具和(在中有文档)为你处理批量解码和控制记录过滤。
POST /api/v1/sessionsGET /realtime/v1/sessions/{id}/outPOST /realtime/v1/sessions/{id}/in/appendPOST /api/v1/sessions/{id}/closeChatInputChunk{ kind: "message"; payload: ChatTaskWirePayload } | { kind: "stop"; message? }ChatTaskWirePayloadchatIdtriggersubmit-message | regenerate-message | preload | close | action | handover-preparemessage?metadata?action?continuation?previousRunId?trigger-control: turn-completepublic-access-tokensession-in-event-idtrigger-control: upgrade-requiredSSEStreamSubscriptioncontrolSubtype(headers)docs/ai-chat/client-protocol.mdxCommon mistakes
常见错误
-
CRITICAL: sending a follow-up by re-POSTing.
POST /api/v1/sessionsts// Wrong - a cached re-POST silently drops basePayload.message; basePayload is trigger config, not a channel await fetch("/api/v1/sessions", { method: "POST", body: JSON.stringify({ ...createBody }) }); // Correct - append to the session's input channel await fetch(`/realtime/v1/sessions/${id}/in/append`, { method: "POST", body: JSON.stringify({ kind: "message", payload }) }); -
Using the wrong token for/
.in. Use.outfrom the create response body (session-scoped). ThepublicAccessTokenresponse header is run-scoped and cannot subscribe.x-trigger-jwt -
Initializingin
chat.local. It is skipped on continuation runs, soonChatStartcrashes withrun(). Init inchat.local can only be modified after initialization.onBoot -
for the message-history write. A mid-stream refresh would read
chat.defer.[]that write inline before the model streams; reserveawaitfor analytics, audit, cache warming.chat.defer -
Giving the HITL tool an.
executecalls it immediately. Leave it execute-less; the frontend supplies the answer viastreamText+addToolOutput.sendAutomaticallyWhen -
Declaring sub-agent / heavy tools only on. Also declare them on
streamText(or pass tochat.agent({ tools })in a custom agent) soconvertToModelMessages(uiMessages, { tools })re-applies on every turn.toModelOutput -
Importing heavy-execute tools into the Head Start route module. This is a build-time import chain problem; runtime strip helpers do not fix it. Keep schemas in an+
ai-only module.zod -
Returning a megabyte tool output on the stream. Onerecord over ~1 MiB throws
tool-output-available. Persist to your store, write the row first, then emit only an id.ChatChunkTooLargeError -
Settingon the active-send path. It races the new turn's first chunk and closes the stream early. Use it only on reconnect-on-reload paths.
X-Peek-Settled: 1
Note on docs vocabulary: agent-side examples in some docs still use the legacychunk type. That is the agent-emit vocabulary. A custom reader must filter on thetrigger:turn-completeheader, not ontrigger-control.chunk.typeMCP-driven agent chats (,list_agents,start_agent_chat,send_agent_message) are MCP server tools used from Claude Code / Cursor, not importable SDK functions. Seeclose_agent_chat./mcp-tools#agent-chat-tools
-
严重错误:通过重新POST发送后续消息。
POST /api/v1/sessionsts// 错误 - 缓存的重新POST会静默丢弃basePayload.message;basePayload是触发器配置,而非通道 await fetch("/api/v1/sessions", { method: "POST", body: JSON.stringify({ ...createBody }) }); // 正确 - 追加到会话的输入通道 await fetch(`/realtime/v1/sessions/${id}/in/append`, { method: "POST", body: JSON.stringify({ kind: "message", payload }) }); -
为/
.in使用错误的令牌。 使用创建响应体中的.out(会话作用域)。publicAccessToken响应头是运行作用域的,无法用于订阅。x-trigger-jwt -
在中初始化
onChatStart。 续运行会跳过此步骤,导致chat.local因run()崩溃。请在chat.local can only be modified after initialization中初始化。onBoot -
使用处理消息历史写入。 流中刷新会读取到
chat.defer。在模型流式传输前内联[]该写入操作;将await保留用于分析、审计、缓存预热。chat.defer -
为HITL工具设置。
execute会立即调用它。不要设置execute;前端通过streamText+addToolOutput提供答案。sendAutomaticallyWhen -
仅在上声明子代理/重型工具。 还需在
streamText上声明(或在自定义代理中传递给chat.agent({ tools })),以便convertToModelMessages(uiMessages, { tools })在每一轮都重新生效。toModelOutput -
将重型执行工具导入Head Start路由模块。 这会导致构建时导入链问题;运行时剥离工具无法解决。请将Schema放在仅包含+
ai的模块中。zod -
在流上返回兆字节级的工具输出。 超过~1 MiB的记录会抛出
tool-output-available。将其持久化到你的存储中,先写入行,然后仅发出ID。ChatChunkTooLargeError -
在主动发送路径上设置。 这会与新轮次的第一个块竞争,导致流提前关闭。仅在重新加载时重新连接的路径上使用。
X-Peek-Settled: 1
文档词汇说明:部分文档中的代理端示例仍使用旧版块类型。这是代理端的术语。自定义读取器必须过滤trigger:turn-complete头部,而非trigger-control。chunk.typeMCP驱动的代理聊天(、list_agents、start_agent_chat、send_agent_message)是用于Claude Code/Cursor的MCP服务工具,并非可导入的SDK函数。请查看close_agent_chat。/mcp-tools#agent-chat-tools
References
参考资料
- skill - the everyday
trigger-authoring-chat-agentdefinition, lifecycle hooks, and thechat.agent({...})happy path. Start there before reaching for this skill.useTriggerChatTransport - skill - Realtime hooks and frontend streaming beyond the chat transport.
trigger-realtime - skill - base
trigger-taskssemantics,task(), and standard lifecycle hooks.ctx
Reference docs ship beside this skill in the same package, read them locally (no network), pinned to your installed version. The frontmatter above lists every doc this skill draws from, all under (including ). For HITL, sessions, and sub-agents start with , , , , .
sources:@trigger.dev/sdk/docs/ai-chat/patterns/sessions.mdxserver-chat.mdxclient-protocol.mdxpatterns/human-in-the-loop.mdxpatterns/sub-agents.mdxFor and build extensions a chat-agent task may need (Prisma, Playwright, Python, etc.), read the bundled config docs under ( for the per-extension setup).
trigger.config.ts@trigger.dev/sdk/docs/config/config/extensions/- 技能 - 日常
trigger-authoring-chat-agent定义、生命周期钩子以及chat.agent({...})的常规使用路径。在使用本技能前,请先从该技能开始。useTriggerChatTransport - 技能 - 聊天传输层之外的实时钩子和前端流式传输。
trigger-realtime - 技能 - 基础
trigger-tasks语义、task()以及标准生命周期钩子。ctx
参考文档与本技能捆绑在同一个包中,可本地阅读(无需网络),并与你安装的版本保持一致。上方的前置元数据列出了本技能引用的所有文档,均位于下(包括)。对于人机协同、会话和子代理,请从、、、、开始阅读。
sources:@trigger.dev/sdk/docs/ai-chat/patterns/sessions.mdxserver-chat.mdxclient-protocol.mdxpatterns/human-in-the-loop.mdxpatterns/sub-agents.mdx关于聊天代理任务可能需要的和构建扩展(Prisma、Playwright、Python等),请阅读下的捆绑配置文档(每个扩展的设置请查看)。
trigger.config.ts@trigger.dev/sdk/docs/config/config/extensions/Version
版本
This skill is bundled inside and read directly from , so it always matches your installed SDK version (see the adjacent ). The full documentation for these APIs ships alongside it under .
@trigger.dev/sdknode_modulespackage.json@trigger.dev/sdk/docs/本技能捆绑在中,直接从读取,因此始终与你安装的SDK版本匹配(请查看相邻的)。这些API的完整文档与本技能一起位于下。
@trigger.dev/sdknode_modulespackage.json@trigger.dev/sdk/docs/