--- name: delegate-to-agent description: >- How to delegate all AI work to the agent chat. Use when delegating AI work from UI or scripts to the agent, when a user asks for agent behavior or LLM-powered features, when tempted to add inline LLM calls, or when sending messages to the agent from application code. scope: dev metadata: internal: true --- # Delegate All AI to the Agent ## Rule The UI never calls an LLM directly. Product workflows are delegated to the agent through the chat bridge so users can see, steer, and audit the work. Server-side one-shot model calls are an explicit escape hatch for narrow text transforms only; use `completeText()` from `@agent-native/core/server` when the work intentionally does not need tools, chat history, or run state. ## Why The agent is the single AI interface. It has context about the full project, can read/write any file, and can run scripts. Inline LLM calls bypass this — they create a shadow AI that doesn't know what the agent knows and can't coordinate with it. ## How **From the UI (client):** ```ts import { sendToAgentChat } from "@agent-native/core/client/agent-chat"; sendToAgentChat({ message: "Generate a summary of this document", context: documentContent, // optional hidden context (not shown in chat UI) submit: true, // auto-submit to the agent }); ``` **From the UI, in the background:** ```ts import { sendToAgentChat } from "@agent-native/core/client/agent-chat"; sendToAgentChat({ message: "Analyze this import and create any missing records", context: `Import batch id: ${batchId}`, submit: true, newTab: true, background: true, openSidebar: false, }); ``` This is still a full agent run: tools, actions, thread state, and run tracking all remain active. It simply does not focus or open the sidebar. **From scripts (Node):** ```ts import { agentChat } from "@agent-native/core"; agentChat.submit("Process the uploaded images and create thumbnails"); ``` **For narrow server-side text transforms:** ```ts import { completeText } from "@agent-native/core/server"; const result = await completeText({ systemPrompt: "Return exactly one sentiment label.", input: messageBody, maxOutputTokens: 12, temperature: 0, }); ``` Wrap user-facing uses in actions so the UI and agent share the same operation. Do not call provider SDKs directly. **From the UI, detecting when agent is done:** ```ts import { useAgentChatGenerating } from "@agent-native/core/client/agent-chat"; function MyComponent() { const isGenerating = useAgentChatGenerating(); // Show loading state while agent is working } ``` ## `submit` vs Prefill The `submit` option controls whether the message is sent automatically or placed in the chat input for user review: | `submit` value | Behavior | Use when | | -------------- | --------------------------------------- | ----------------------------------------------------------------------------------- | | `true` | Auto-submits to the agent immediately | Routine operations the user has already approved | | `false` | Prefills the chat input for user review | High-stakes operations (deleting data, modifying code, API calls with side effects) | | omitted | Uses the project's default setting | General-purpose delegation | ```ts // Auto-submit: routine operation sendToAgentChat({ message: "Update the project summary", submit: true }); // Prefill: let user review before sending sendToAgentChat({ message: "Delete all projects older than 30 days", submit: false, }); ``` ## Capture user input first when generating from a prompt Buttons that produce new content ("New Design", "Create Dashboard", "Make Deck", "Generate Form") need the user's prompt as input. **Never hardcode a generic message** — the result will be a generic generation the user didn't actually ask for. **Bad** — auto-submits a placeholder message; the user never said what they wanted: ```tsx ``` **Good** — Popover anchored to the button captures the prompt, then submits it: ```tsx