create-client-tool

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Create a Client Tool

创建客户端工具

Scaffold a new
AtlasTool
named $ARGUMENTS and wire it into the app.
生成一个名为**$ARGUMENTS**的新
AtlasTool
并将其接入应用。

Background

背景

Client tools let the Atlas Agent invoke logic that runs in the browser — rendering charts, querying local state, showing UI panels, triggering navigation, etc. The agent decides when to call the tool; the app executes it and returns a result.
The flow is:
  1. Agent responds with a
    clientTool
    action
  2. The library validates the arguments against the TypeBox schema
  3. execute()
    runs in the browser and returns
    { output, details }
  4. output
    (string) is sent back to the agent as the tool result
  5. details
    (any shape) is available on
    message.toolCalls
    for the UI to render

客户端工具允许Atlas Agent调用在浏览器中运行的逻辑——例如渲染图表、查询本地状态、显示UI面板、触发导航等。由Agent决定何时调用工具;应用执行工具并返回结果。
流程如下:
  1. Agent返回
    clientTool
    动作
  2. 库根据TypeBox schema验证参数
  3. execute()
    在浏览器中运行并返回
    { output, details }
  4. output
    (字符串)作为工具结果发送回Agent
  5. details
    (任意格式)可通过
    message.toolCalls
    供UI渲染使用

Step 1 — Understand the codebase

步骤1 — 了解代码库

Before writing anything, read:
  • The file where
    useAtlasChat
    is called (likely
    src/App.tsx
    ) to find where
    tools
    is passed
  • Any existing tool definitions to match the file/naming conventions

在编写任何代码之前,请阅读:
  • 调用
    useAtlasChat
    的文件(通常是
    src/App.tsx
    ),找到传入
    tools
    的位置
  • 任何现有工具定义,以匹配文件/命名规范

Step 2 — Define the tool

步骤2 — 定义工具

Create the tool as a typed constant. Use
Type
from
@cognite/dune-industrial-components/atlas-agent
to define the parameters schema — this gives both compile-time types and runtime validation.
ts
import { Type } from "@cognite/dune-industrial-components/atlas-agent";
import type { AtlasTool } from "@cognite/dune-industrial-components/atlas-agent";

export const myTool: AtlasTool = {
  name: "my_tool",            // snake_case — this is what the agent uses to invoke it
  description:
    "One sentence describing what this tool does and when the agent should call it.",
  parameters: Type.Object({
    exampleParam: Type.String({ description: "What this param is for" }),
    optionalNum: Type.Optional(Type.Number({ description: "..." })),
  }),
  execute: async (args) => {
    // args is fully typed from the schema above
    // Do the work here — call APIs, update state, render UI, etc.
    return {
      output: "Plain text summary sent back to the agent",
      details: {
        // Any structured data you want available in the UI via message.toolCalls
      },
    };
  },
};
将工具创建为类型化常量。使用
@cognite/dune-industrial-components/atlas-agent
中的
Type
来定义参数schema——这同时提供编译时类型和运行时验证。
ts
import { Type } from "@cognite/dune-industrial-components/atlas-agent";
import type { AtlasTool } from "@cognite/dune-industrial-components/atlas-agent";

export const myTool: AtlasTool = {
  name: "my_tool",            // snake_case — Agent将使用此名称调用工具
  description:
    "一句话描述该工具的功能以及Agent应何时调用它。",
  parameters: Type.Object({
    exampleParam: Type.String({ description: "此参数的用途" }),
    optionalNum: Type.Optional(Type.Number({ description: "..." })),
  }),
  execute: async (args) => {
    // args完全遵循上述schema的类型
    // 在此处执行操作——调用API、更新状态、渲染UI等
    return {
      output: "发送回Agent的纯文本摘要",
      details: {
        // 任何你希望通过message.toolCalls在UI中使用的结构化数据
      },
    };
  },
};

TypeBox quick reference

TypeBox快速参考

SchemaUsage
Type.String()
string
Type.Number()
number
Type.Boolean()
boolean
Type.Literal("foo")
exact value
Type.Union([Type.Literal("a"), Type.Literal("b")])
enum
Type.Array(Type.String())
string[]
Type.Object({ ... })
object
Type.Optional(...)
mark any field optional
Always add a
description
to each field — the agent uses these to understand what to pass.

Schema用法
Type.String()
字符串
Type.Number()
数字
Type.Boolean()
布尔值
Type.Literal("foo")
精确值
Type.Union([Type.Literal("a"), Type.Literal("b")])
枚举
Type.Array(Type.String())
字符串数组
Type.Object({ ... })
对象
Type.Optional(...)
将任意字段标记为可选
务必为每个字段添加
description
——Agent会根据这些描述来理解需要传入什么参数。

Step 3 — Wire into useAtlasChat

步骤3 — 接入useAtlasChat

Find the
useAtlasChat
call and add the tool to the
tools
array:
ts
const { messages, send, ... } = useAtlasChat({
  client: isLoading ? null : sdk,
  agentExternalId: AGENT_EXTERNAL_ID,
  tools: [myTool],   // add here
});

找到
useAtlasChat
的调用位置,并将工具添加到
tools
数组中:
ts
const { messages, send, ... } = useAtlasChat({
  client: isLoading ? null : sdk,
  agentExternalId: AGENT_EXTERNAL_ID,
  tools: [myTool],   // 在此处添加
});

Step 4 — Render tool results (if needed)

步骤4 — 渲染工具结果(如有需要)

If the tool returns structured
details
, render them in the message list.
message.toolCalls
is a
ToolCall[]
— one entry per tool call (client-side and server-side) in call order.
tsx
{msg.toolCalls?.map((tc, i) => (
  // tc.name    — tool name
  // tc.output  — the string sent back to the agent
  // tc.details — your structured data (cast to your known shape)
  <MyToolOutput key={i} data={tc.details as MyToolDetails} />
))}

如果工具返回结构化的
details
,请在消息列表中渲染它们。
message.toolCalls
ToolCall[]
——按调用顺序排列的每个工具调用(客户端和服务器端)的条目。
tsx
{msg.toolCalls?.map((tc, i) => (
  // tc.name    — 工具名称
  // tc.output  — 发送回Agent的字符串
  // tc.details — 你的结构化数据(转换为你已知的类型)
  <MyToolOutput key={i} data={tc.details as MyToolDetails} />
))}

Done

完成

The agent can now invoke
$ARGUMENTS
. Describe what it does clearly in the
description
field — the agent relies on that string to decide when and how to call the tool.
现在Agent可以调用
$ARGUMENTS
了。请在
description
字段中清晰描述其功能——Agent依赖该字符串来决定何时以及如何调用工具。