setup-python-tools

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Set Up Python Tool Execution

设置Python工具执行

Add client-side Python tool execution via Pyodide to this Dune app.
Target: $ARGUMENTS
通过Pyodide为该Dune应用添加客户端Python工具执行功能。
目标:$ARGUMENTS

Background

背景

Atlas agents can have Python tools defined in their CDF config (
type: "runPythonCode"
). When the agent calls one, it arrives as a
toolConfirmation
(auto-allowed) followed by a
clientTool
action. The library fetches the tool's Python code from the agent config automatically and executes it via the provided
pythonRuntime
.
You only need to:
  1. Set up
    usePyodideRuntime
    to get a runtime instance
  2. Pass
    pythonRuntime
    to
    useAtlasChat
No
PythonToolConfig
entries — the library reads the code from the agent's CDF config.
The flow is:
  1. usePyodideRuntime
    loads Pyodide (~30MB, cached after first load), installs packages, and injects Cognite SDK credentials into the Python environment
  2. When the agent calls a Python tool, the library fetches its code from the agent's CDF config (cached per session), wraps it, executes it in Pyodide, and returns the result

Atlas Agent可在其CDF配置中定义Python工具(
type: "runPythonCode"
)。当Agent调用该工具时,会先发送一个
toolConfirmation
(自动允许),随后触发
clientTool
操作。库会自动从Agent配置中获取工具的Python代码,并通过提供的
pythonRuntime
执行。
你只需完成以下步骤:
  1. 配置
    usePyodideRuntime
    以获取运行时实例
  2. pythonRuntime
    传入
    useAtlasChat
无需配置
PythonToolConfig
条目 —— 库会从Agent的CDF配置中读取代码。
流程如下:
  1. usePyodideRuntime
    加载Pyodide(约30MB,首次加载后会缓存)、安装包,并将Cognite SDK凭证注入Python环境
  2. 当Agent调用Python工具时,库会从Agent的CDF配置中获取其代码(按会话缓存)、进行包装、在Pyodide中执行,并返回结果

Step 1 — Understand the app

步骤1 —— 了解应用

Read these files before touching anything:
  • package.json
    — detect package manager and existing deps
  • The component that calls
    useAtlasChat
    — understand current tools/config

在修改任何内容前,请先阅读以下文件:
  • package.json
    —— 检测包管理器和已存在的依赖
  • 调用
    useAtlasChat
    的组件 —— 了解当前工具/配置

Step 2 — Install Pyodide

步骤2 —— 安装Pyodide

Install exactly
pyodide@0.29.3
using the app's package manager. This version must match the CDN artifacts loaded at runtime — installing a different version will cause errors.
  • pnpm →
    pnpm add pyodide@0.29.3
  • npm →
    npm install pyodide@0.29.3
  • yarn →
    yarn add pyodide@0.29.3
Note:
@cognite/dune-industrial-components
,
@sinclair/typebox
,
ajv
,
ajv-formats
should already be installed. If not, install them too (see the
integrate-atlas-chat
skill).

使用应用的包管理器精确安装
pyodide@0.29.3
。 该版本必须与运行时加载的CDN工件版本匹配 —— 安装不同版本会导致错误。
  • pnpm →
    pnpm add pyodide@0.29.3
  • npm →
    npm install pyodide@0.29.3
  • yarn →
    yarn add pyodide@0.29.3
注意
@cognite/dune-industrial-components
@sinclair/typebox
ajv
ajv-formats
应已安装。如果未安装,请一并安装(参考
integrate-atlas-chat
Skill)。

Step 3 — Set up usePyodideRuntime

步骤3 —— 配置usePyodideRuntime

In the component that calls
useAtlasChat
, add the Pyodide runtime hook:
tsx
import { loadPyodide } from "pyodide";
import { usePyodideRuntime } from "@cognite/dune-industrial-components/atlas-agent/pyodide";
import { useAtlasChat } from "@cognite/dune-industrial-components/atlas-agent/react";

function MyChat() {
  const { sdk, isLoading } = useDune();

  // Initialize Python runtime (loads Pyodide, installs packages, sets up Cognite SDK)
  const {
    runtime: pythonRuntime,
    loading: pythonLoading,
    progress: pythonProgress,
    error: pythonError,
    isReady: pythonReady,
  } = usePyodideRuntime({
    loadPyodide,
    client: isLoading ? null : sdk,
    requirements: ["pandas", "numpy"],    // optional — additional packages
  });

  // ... useAtlasChat below
}
在调用
useAtlasChat
的组件中,添加Pyodide运行时钩子:
tsx
import { loadPyodide } from "pyodide";
import { usePyodideRuntime } from "@cognite/dune-industrial-components/atlas-agent/pyodide";
import { useAtlasChat } from "@cognite/dune-industrial-components/atlas-agent/react";

function MyChat() {
  const { sdk, isLoading } = useDune();

  // 初始化Python运行时(加载Pyodide、安装包、配置Cognite SDK)
  const {
    runtime: pythonRuntime,
    loading: pythonLoading,
    progress: pythonProgress,
    error: pythonError,
    isReady: pythonReady,
  } = usePyodideRuntime({
    loadPyodide,
    client: isLoading ? null : sdk,
    requirements: ["pandas", "numpy"],    // 可选 —— 额外包
  });

  // ... 下方使用useAtlasChat
}

Hook API reference

钩子API参考

Return fieldTypeDescription
runtime
PythonRuntime | undefined
The initialized runtime, or undefined if not ready
loading
boolean
True while Pyodide is loading / initializing
error
string | null
Error message if initialization failed
progress
{ stage: string; percent: number }
Current init progress for UI display
isReady
boolean
Convenience:
!loading && !error && runtime !== undefined
返回字段类型描述
runtime
PythonRuntime | undefined
已初始化的运行时,未就绪时为undefined
loading
boolean
Pyodide加载/初始化时为true
error
string | null
初始化失败时的错误信息
progress
{ stage: string; percent: number }
用于UI展示的当前初始化进度
isReady
boolean
便捷属性:
!loading && !error && runtime !== undefined

Loading state UI

加载状态UI

Place the loading indicator above the chat input, not in the message list. Keep it compact — a pill/badge showing stage text and percent. Show an error badge separately. First load is ~30-60s (downloads ~30MB); subsequent loads are <2s from browser cache.
tsx
{/* Loading — shown above the input while Pyodide initializes */}
{pythonLoading && (
  <div className="flex items-center gap-2 rounded-lg border bg-muted/50 px-3 py-2 text-sm text-muted-foreground">
    {/* Optional: <IconBrandPython /> from @tabler/icons-react */}
    <span>{pythonProgress.stage || "Initializing Python..."}</span>
    {pythonProgress.percent > 0 && pythonProgress.percent < 100 && (
      <span className="text-xs opacity-70">({pythonProgress.percent}%)</span>
    )}
  </div>
)}

{/* Error — shown if init fails (after loading finishes) */}
{pythonError && !pythonLoading && (
  <div className="flex items-center gap-2 rounded-lg border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive">
    <span>Python runtime failed to load</span>
  </div>
)}

将加载指示器放置在聊天输入框上方,而非消息列表中。 保持紧凑 —— 使用胶囊/徽章样式显示阶段文本和百分比。单独显示错误徽章。首次加载约30-60秒(下载约30MB);后续加载从浏览器缓存读取,耗时<2秒。
tsx
{/* 加载中 —— Pyodide初始化时显示在输入框上方 */}
{pythonLoading && (
  <div className="flex items-center gap-2 rounded-lg border bg-muted/50 px-3 py-2 text-sm text-muted-foreground">
    {/* 可选:来自@tabler/icons-react的<IconBrandPython /> */}
    <span>{pythonProgress.stage || "初始化Python..."}</span>
    {pythonProgress.percent > 0 && pythonProgress.percent < 100 && (
      <span className="text-xs opacity-70">({pythonProgress.percent}%)</span>
    )}
  </div>
)}

{/* 错误 —— 加载完成后初始化失败时显示 */}
{pythonError && !pythonLoading && (
  <div className="flex items-center gap-2 rounded-lg border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive">
    <span>Python运行时加载失败</span>
  </div>
)}

Step 4 — Wire into useAtlasChat

步骤4 —— 接入useAtlasChat

Pass the runtime to
useAtlasChat
. That's all — no tool configs needed:
tsx
const { messages, send, isStreaming, progress, error, reset, abort } = useAtlasChat({
  client: isLoading ? null : sdk,
  agentExternalId: "my-agent",
  tools: [renderTimeSeries],   // regular client tools (declared to agent), if any
  pythonRuntime,               // from usePyodideRuntime — enables Python tool execution
});
Note: Python tools are NOT declared to the agent via
tools
. The agent already knows about them from its CDF config. The library fetches the code automatically when needed.

将运行时传入
useAtlasChat
。仅此而已 —— 无需工具配置:
tsx
const { messages, send, isStreaming, progress, error, reset, abort } = useAtlasChat({
  client: isLoading ? null : sdk,
  agentExternalId: "my-agent",
  tools: [renderTimeSeries],   // 常规客户端工具(已向Agent声明)(如有)
  pythonRuntime,               // 来自usePyodideRuntime —— 启用Python工具执行
});
注意:Python工具无需通过
tools
向Agent声明。Agent已通过其CDF配置知晓这些工具。库会在需要时自动获取代码。

Step 5 — Disable input while Python loads

步骤5 —— Python加载时禁用输入

The user shouldn't send messages before the runtime is ready. Disable the entire input area (not just the send button) so the state is unambiguous:
tsx
<ChatInput
  onSend={handleSend}
  disabled={isStreaming || pythonLoading}
  // ...
/>
If you have a home page with suggestion chips, disable those too:
tsx
<ChatHomePage
  onSuggestionClick={handleSuggestionClick}
  disabled={pythonLoading}
/>

用户不应在运行时就绪前发送消息。禁用整个输入区域(而非仅发送按钮),确保状态明确:
tsx
<ChatInput
  onSend={handleSend}
  disabled={isStreaming || pythonLoading}
  // ...
/>
如果主页有建议芯片,也请禁用它们:
tsx
<ChatHomePage
  onSuggestionClick={handleSuggestionClick}
  disabled={pythonLoading}
/>

Done

完成

The app can now execute Python tools client-side via Pyodide. When the agent calls a Python tool, the library automatically fetches its code from the agent config, runs it in the browser, and returns the result to the agent.
应用现在可通过Pyodide在客户端执行Python工具。当Agent调用Python工具时,库会自动从Agent配置中获取代码、在浏览器中运行,并将结果返回给Agent。