Skip to main content

integrate-fusion-agent

MUST be used when adding AI, Atlas, an agent, a chat UI, or LLM features to a Flows/Fusion app. Use the Atlas/EOS sidebar via @cognite/app-sdk — not useAtlasChat, vendored atlas-agent, or per-row chat completions. Triggers: atlas, EOS, PAIA, agent chat, chat UI, sendAgentMessage, sendAgentLayoutMode, registerAgentServer, connectToHostApp, useAtlasChat, LLM. In-app chat: integrate-atlas-chat only if the host sidebar cannot work.

インストールへ移動

ソース情報

リポジトリ
cognitedata/builder-skills
ソースの最終更新活動
2026年9月1日 10:41
検出された SKILL.md の言語
英語
スター
6
フォーク
1

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
integrate-fusion-agent
description
MUST be used when adding AI, Atlas, an agent, a chat UI, or LLM features to a Flows/Fusion app. Use the Atlas/EOS sidebar via @cognite/app-sdk — not useAtlasChat, vendored atlas-agent, or per-row chat completions. Triggers: atlas, EOS, PAIA, agent chat, chat UI, sendAgentMessage, sendAgentLayoutMode, registerAgentServer, connectToHostApp, useAtlasChat, LLM. In-app chat: integrate-atlas-chat only if the host sidebar cannot work.
allowed-tools
Read, Glob, Grep, Edit, Write, Bash
# Integrate Atlas / EOS Sidebar Default AI path: the platform Atlas sidebar (EOS / Fusion PAIA) via `@cognite/app-sdk`. Do not embed `useAtlasChat`, vendor `atlas-agent`, or call third-party LLM APIs. `integrate-atlas-chat` only if the user explicitly requires in-app chat **and** `connectToHostApp` cannot provide the sidebar (standalone app; always rejects). There is no manifest field for this. Implement only what is needed: 1. **Open** — Topbar Atlas button; `sendAgentLayoutMode` for in-app triggers 2. **Message** — `sendAgentMessage` to inject context 3. **Server** — resources (app state) and actions (tools) --- ## Step 0 — Read the app - `package.json` — package manager, `@cognite/app-sdk` - `src/App.tsx` — structure, existing SDK usage Ask which of the three capabilities are needed. Do not offer an in-app chat unless they already insisted. --- ## Step 1 — Install `pnpm add @cognite/app-sdk` (or npm/yarn). Minimum `0.3.1`. --- ## Step 2 — Connect to the host `connectToHostApp` rejects outside Fusion (standalone `vite dev`). Catch that; hide agent triggers when `api` is null. Comlink proxies are callable — `setApi(proxy)` makes React treat the proxy as an updater and stores a Promise. Always `setApi(() => resolvedApi)`. ```typescript // src/hooks/useHostApp.ts import { useState, useEffect } from 'react'; import { connectToHostApp, type HostAppAPI } from '@cognite/app-sdk'; export function useHostApp(): HostAppAPI | null { const [api, setApi] = useState<HostAppAPI | null>(null); useEffect(() => { connectToHostApp({ applicationName: 'my-app' }) .then(({ api: resolvedApi }) => setApi(() => resolvedApi)) .catch(() => { /* outside Fusion — no-op */ }); }, []); return api; } ``` Call at the root; pass `api` down or via context. `typeof proxy.method === 'function'` is always true — do not feature-detect with `typeof`; use try/catch. --- ## Step 3 — Open the sidebar Primary launcher: Aura Topbar Atlas (`systemActions.atlas.visible: true`, see `use-topbar`). No second "Open Assistant" control. `sendAgentLayoutMode` is for contextual triggers only (`sidebar` | `fullscreen` | `closed`): ```typescript await api.sendAgentLayoutMode({ mode: 'sidebar' }); ``` --- ## Step 4 — Send a message Pair with `sendAgentLayoutMode`. `newSession: true` for a new task from an item; omit to continue the thread. Put names/IDs/state in the message — one sidebar turn, not N completions over query rows. ```typescript await api.sendAgentLayoutMode({ mode: 'sidebar' }); await api.sendAgentMessage({ message: `Analyse the schedule for "${itemName}" and suggest how to reduce total duration.`, newSession: true, }); ``` --- ## Step 5 — Agent server Register on mount, unregister on unmount. Factories take services as args so they can be unit-tested without React: ``` src/features/agent/ agentActions.ts — (deps) => Action[] agentResources.ts — (deps) => Resource[] useAgentServer.ts — register / unregister ``` Resource `read()` returns `{ type: 'json', data }` (preferred) or `{ type: 'text', text }`. Write `description` like a docstring. ```typescript // src/features/agent/agentResources.ts import { createAgentResource } from '@cognite/app-sdk'; export function buildAgentResources(storage: StorageService) { return [ createAgentResource({ uri: 'my-app://current-state', name: 'Current application state', description: 'Items currently visible, their statuses, and active filters. Read before answering questions about what the user is looking at.', async read() { return [{ type: 'json', data: storage.getAll() }]; }, }), ]; } ``` Actions: `snake_case` names, Zod params, `.describe()` on every field. The agent does **not** confirm before calling — mutating actions must say so in `description` and require prior user approval. ```typescript // src/features/agent/agentActions.ts import { createAgentAction } from '@cognite/app-sdk'; import { z } from 'zod'; export function buildAgentActions(dataService: DataService) { return [ createAgentAction({ name: 'get_item_details', description: 'Full details for an item by ID, including history.', parameters: z.object({ item_id: z.string().describe('The ID of the item to retrieve'), }), async handler({ item_id }) { const item = await dataService.getItem(item_id); return { content: [{ type: 'json', data: item }] }; }, }), ]; } ``` ```typescript createAgentAction({ name: 'update_item_status', description: 'Update item status. Call ONLY when the user has explicitly approved the change.', parameters: z.object({ item_id: z.string().describe('The item to update'), status: z.enum(['active', 'closed', 'pending']).describe('The new status'), }), async handler({ item_id, status }) { storage.updateStatus(item_id, status); return { content: [{ type: 'json', data: { success: true } }] }; }, }) ``` ```typescript // src/features/agent/useAgentServer.ts import { useEffect } from 'react'; import { createAgentServer, registerAgentServer, type HostAppAPI } from '@cognite/app-sdk'; import { buildAgentActions } from './agentActions'; import { buildAgentResources } from './agentResources'; import { useStorageService } from '../storage/StorageServiceContext'; import { useDataService } from '../data/DataServiceContext'; export function useAgentServer(api: HostAppAPI | null): void { const storage = useStorageService(); const dataService = useDataService(); useEffect(() => { if (!api) return; const server = createAgentServer({ uri: 'my-app', // Fusion namespaces with instance ID actions: buildAgentActions(dataService), resources: buildAgentResources(storage), }); void registerAgentServer(api, server).catch((err: unknown) => { console.warn('[agent] registerAgentServer failed:', err); }); return () => { void api.unregisterAgentServer('my-app').catch((err: unknown) => { console.warn('[agent] unregisterAgentServer failed:', err); }); }; }, [api, storage, dataService]); } ``` --- ## Step 6 — Wire together ```tsx function App() { const api = useHostApp(); useAgentServer(api); return ( <AppLayout> <MainContent onAnalyseItem={async (item) => { if (!api) return; await api.sendAgentLayoutMode({ mode: 'sidebar' }); await api.sendAgentMessage({ message: `Analyse "${item.name}" (id: ${item.id}).`, newSession: true, }); }} /> </AppLayout> ); } ``` Test factories directly: ```typescript const [getItemAction] = buildAgentActions({ getItem: vi.fn().mockResolvedValue({ id: '1', name: 'Test' }), }); const result = await getItemAction.handler({ item_id: '1' }); expect(result.content[0].data).toEqual({ id: '1', name: 'Test' }); ``` --- ## Hard gate — LLM calls over query results Do not map chat completions (Atlas `agents/chat`, OpenAI/Anthropic, `useAtlasChat().send`) over DMS/SDK rows. Prefer one `sendAgentMessage` or a resource the sidebar agent can read. If per-item completions are an explicit product requirement (default: no): | Rule | Limit | | --- | --- | | Default | **5** completions per user-initiated action | | Ceiling | **50** — never generate code that can exceed this | | Cache | `space:externalId:lastUpdatedTime`; hits do not spend budget | | Batch | One prompt covering N items, not N calls | | Trigger | User-initiated only — never on render, poll, or an unbounded list | | UX | Say when the cap truncated the set | Forbidden: `items.map((row) => complete(row))`, `Promise.all` of completions over a query page. --- ## Checklist - [ ] Topbar Atlas launcher (`use-topbar`); no in-app chat widget - [ ] `@cognite/app-sdk@0.3.1+`; `setApi(() => resolvedApi)`; catch outside-Fusion rejection - [ ] Triggers hidden when `api` is null; server registered/unregistered with `.catch()` - [ ] Resource descriptions say what/when; action names `snake_case`; mutating actions require prior approval - [ ] Factories take services as args; LLM-over-rows capped (5 / max 50) and cached if present
GitHubで見る