mcpField
S
setup-python-tools

setup-python-tools

github.com/cognitedataAgent workflows61.9k installsUpdated 1d ago
Repository

About setup-python-tools

A setup skill for adding browser-side Python execution to an Atlas Chat app using Pyodide. It guides developers through installation, runtime wiring, loading UI, and disabling chat input until initialization is complete.

Key features

  1. 01Pyodide-based browser execution
  2. 02usePyodideRuntime setup guidance
  3. 03Atlas Chat runtime wiring
  4. 04Initialization progress and error UI
  5. 05Input disabling during loading

Use cases

  1. 01Enabling an agent's configured Python tools in a web chat
  2. 02Adding runtime loading status above a chat input
  3. 03Preventing messages before Python initialization

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/cognitedata/builder-skills --skill setup-python-tools

After installing, type/setup-python-toolsin Claude Code to confirm it loaded.

Details

From the project README

Set Up Python Tool Execution

Add client-side Pyodide execution for $ARGUMENTS. Skip this if the app uses the Atlas / EOS sidebar (integrate-fusion-agent).

Prerequisite: src/atlas-agent/ from integrate-atlas-chat, plus @sinclair/typebox. Copy python.ts, pyodide.ts, pyodide-react.ts, pyodide-runtime.ts from integrate-atlas-chat/code/ into src/atlas-agent/.

CDF runPythonCode tools arrive as toolConfirmation + clientTool. Wire usePyodideRuntime and pass pythonRuntime to useAtlasChat — no PythonToolConfig entries. Pyodide is ~30MB, cached after first load.


Step 1 — Understand the app

Read these files before touching anything:

  • package.json — detect package manager and existing deps
  • The component that calls useAtlasChat — understand current tools/config

Step 2 — Install Pyodide

Install exactly [email protected] using the app's package manager. This version must match the CDN artifacts loaded at runtime — installing a different version will cause errors.

@sinclair/typebox should already be installed from integrate-atlas-chat. Add it if missing.


Step 3 — Set up usePyodideRuntime

In the component that calls useAtlasChat, add the Pyodide runtime hook:

import { loadPyodide } from "pyodide";
import { usePyodideRuntime } from "./atlas-agent/pyodide-react";
import { useAtlasChat } from "./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
}
Hook API reference
Return fieldTypeDescription
runtimePythonRuntime | undefinedThe initialized runtime, or undefined if not ready
loadingbooleanTrue while Pyodide is loading / initializing
errorstring | nullError message if initialization failed
progress{ stage: string; percent: number }Current init progress for UI display
isReadybooleanConvenience: !loading && !error && runtime !== undefined
Loading state 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.

{/* 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>
)}

Step 4 — Wire into useAtlasChat

Pass the runtime to useAtlasChat. That's all — no tool configs needed:

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.


Step 5 — Disable input while Python loads

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:

<ChatInput
  onSend={handleSend}
  disabled={isStreaming || pythonLoading}
  // ...
/>

If you have a home page with suggestion chips, disable those too:

<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.

Comments

Markdown supported