create-client-tool
cognitedata/builder-skills
Scaffold and wire AtlasTool client-side tools for Atlas agents with TypeBox schema validation.
What is create-client-tool?
Creates a new AtlasTool for browser-side execution in Atlas agents, handling TypeBox schema definition, execute function, and hook wiring into useAtlasChat. Use this whenever adding a client tool that fetches data, renders UI, calls APIs, shows charts, or performs any browser-side action.
- Generates typed AtlasTool constant with TypeBox schema for parameter validation
- Wires tool into useAtlasChat tools array automatically
- Provides execute() function template for browser-side logic
- Handles tool result output and structured details for UI rendering
- Validates arguments at runtime using TypeBox/AJV stack from integrate-atlas-chat
How to install create-client-tool
npx skills add https://github.com/cognitedata/builder-skills --skill create-client-tool- integrate-atlas-chat skill must be complete (src/atlas-agent/ vendored with TypeBox/AJV)
- @sinclair/typebox package installed
- useAtlasChat hook already integrated in application
How to use create-client-tool
- 1.Read the file where useAtlasChat is called to locate the tools array
- 2.Review existing tool definitions to match naming conventions
- 3.Define the tool as a typed constant using Type from @sinclair/typebox with name, description, parameters schema, and execute function
- 4.Add the tool to the tools array in the useAtlasChat call
- 5.Optionally render tool results by accessing message.toolCalls in your message list component
Use cases
- Create a tool that fetches and displays chart data from a local API
- Build a tool that queries application state and returns formatted results
- Add a tool that triggers UI navigation or shows a modal panel
- Implement a tool that processes user input and updates local state
- Create a tool that calls external APIs and formats responses for the agent
- Frontend developers building Atlas agent applications
- Teams extending agent capabilities with client-side logic
- Developers integrating Atlas chat into React applications
create-client-tool FAQ
Always use this skill when creating any AtlasTool. Do not manually write AtlasTool definitions or wire them into useAtlasChat — this skill ensures proper TypeBox schema, execute function, and hook wiring.
output is a plain text string sent back to the agent as the tool result; details is any structured data available on message.toolCalls for the UI to render.
Wrap the TypeBox type with Type.Optional(), e.g., Type.Optional(Type.Number({ description: "..." }))
Use ./atlas-agent/types if the tool is directly under src/ next to the atlas-agent folder, or adjust the path relative to your tool file location (e.g., ../atlas-agent/types from src/tools/).
Yes, execute() runs in the browser and can call APIs, query local state, render UI, trigger navigation, or perform any browser-side action.
Full instructions (SKILL.md)
Source of truth, from cognitedata/builder-skills.
name: create-client-tool description: "MUST be used whenever creating an AtlasTool (client-side tool) for an Atlas agent. Do NOT manually write AtlasTool definitions or wire them into useAtlasChat — this skill handles the TypeBox schema, execute function, and hook wiring. Prerequisite: integrate-atlas-chat (vendored src/atlas-agent + TypeBox/AJV deps). This includes tools that fetch data, render UI, call APIs, show charts, query local state, or perform any browser-side action. Triggers: AtlasTool, client tool, add tool, create tool, new tool, tool definition, agent tool." allowed-tools: Read, Glob, Grep, Edit, Write metadata: argument-hint: "[tool-name] [brief description of what it does]"
Create a Client Tool
Scaffold a new AtlasTool named $ARGUMENTS and wire it into the app.
Prerequisite
integrate-atlas-chat must already be complete: the app should vend the atlas-agent sources under src/atlas-agent/ (including react.ts) and have @sinclair/typebox installed as in that skill.
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:
- Agent responds with a
clientToolaction - The library validates the arguments against the TypeBox schema
execute()runs in the browser and returns{ output, details }output(string) is sent back to the agent as the tool resultdetails(any shape) is available onmessage.toolCallsfor the UI to render
Step 1 — Understand the codebase
Before writing anything, read:
- The file where
useAtlasChatis called (oftensrc/App.tsxor a chat hook) to find wheretoolsis passed — imports are typically from./atlas-agent/reactafterintegrate-atlas-chat - Any existing tool definitions to match the file/naming conventions
Step 2 — Define the tool
Create the tool as a typed constant. Use Type from @sinclair/typebox to define the parameters schema — this gives both compile-time types and runtime validation (same stack as the vendored atlas-agent from integrate-atlas-chat).
import { Type } from "@sinclair/typebox";
import type { AtlasTool } from "./atlas-agent/types";
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
},
};
},
};
Adjust the ./atlas-agent/... path if the tool file is not directly under src/ next to the atlas-agent folder (for example ../atlas-agent/types from src/tools/).
TypeBox quick reference
| Schema | Usage |
|---|---|
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.
Step 3 — Wire into useAtlasChat
Find the useAtlasChat call and add the tool to the tools array:
const { messages, send, ... } = useAtlasChat({
client: isLoading ? null : sdk,
agentExternalId: AGENT_EXTERNAL_ID,
tools: [myTool], // add here
});
Step 4 — Render tool results (if needed)
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.
{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} />
))}
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.
Related skills
More from cognitedata/builder-skills and the wider catalog.

dependencies-audit
Find and fix dependency vulnerabilities, outdated packages, deprecated dependencies, and license issues in Flows apps.

design
Aura-first UI guidance for Flows and Fusion apps: choose the right primitives, use semantic tokens, and apply consistent patterns.

dm-limits-and-best-practices
Reference for CDF Data Modeling API concurrency limits, pagination, batching, and the QueuedTaskRunner utility.

flows-app-brief
>-

flows-code-review
Run technical code review for Flows app certification with automated file, package, and test coverage assessment.

flows-design-review
>-