MUST be used when adding Pyodide or Python tool support to a Flows app. Do NOT manually configure usePyodideRuntime or wire pythonRuntime into useAtlasChat — this skill handles pyodide installation, hook setup, loading UI, and chat hook wiring. Prerequisite: integrate-atlas-chat (vendored src/atlas-agent + atlas chat wiring). Triggers: Pyodide, Python tools, pythonRuntime, usePyodideRuntime, runPythonCode, Python execution, client-side Python.
71
88%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Critical
Do not install without reviewing
Add client-side Python tool execution via Pyodide to this Flows app.
Target: $ARGUMENTS
integrate-atlas-chat must already be complete: the app should have vendored atlas-agent code under src/atlas-agent/ (including react.ts for useAtlasChat) and the peer dependencies from that skill (@sinclair/typebox, ajv, ajv-formats). Copy the Python-related modules from the integrate-atlas-chat skill code/ directory into src/atlas-agent/ when adding Pyodide (python.ts, pyodide.ts, pyodide-react.ts, pyodide-runtime.ts — see integrate-atlas-chat Step 5).
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:
usePyodideRuntime to get a runtime instancepythonRuntime to useAtlasChatNo PythonToolConfig entries — the library reads the code from the agent's CDF config.
The flow is:
usePyodideRuntime loads Pyodide (~30MB, cached after first load), installs packages,
and injects Cognite SDK credentials into the Python environmentRead these files before touching anything:
package.json — detect package manager and existing depsuseAtlasChat — understand current tools/configInstall 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 add pyodide@0.29.3npm install pyodide@0.29.3yarn add pyodide@0.29.3Note: After
integrate-atlas-chat,@sinclair/typebox,ajv, andajv-formatsshould already be installed. If anything is missing, install the versions listed in that skill's Dependencies table.
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
}| Return field | Type | Description |
|---|---|---|
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 |
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>
)}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.
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}
/>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.
d6af887
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.