Getting Started
Pick your framework
Current npm release: v0.12.0.
Latest docs live at
/docs/. Version-specific docs are published at/docs/<version>/for breaking releases.
Create a starter app
If you want a runnable Askable + CopilotKit example instead of wiring everything by hand, start here:
npm create @askable-ui/app my-app
cd my-app
npm install
npm run devThe scaffold gives you a React + Vite dashboard with data-askable annotations, useAskable() already connected, a CopilotKit sidebar, and a local @copilotkit/runtime server.
npm install @askable-ui/react @askable-ui/corenpm install @askable-ui/react-native @askable-ui/corenpm install @askable-ui/vue @askable-ui/corenpm install @askable-ui/svelte @askable-ui/corenpm install @askable-ui/coreStep 1 — Annotate elements
Add data-askable to any element whose context matters to your AI. The value can be a JSON object or a plain string.
<!-- JSON object — recommended for structured data -->
<div data-askable='{"metric":"revenue","delta":"-12%","period":"Q3"}'>
<RevenueChart />
</div>
<!-- Plain string — fine for simple labels -->
<nav data-askable="main navigation">...</nav>With framework components, use the <Askable> wrapper instead of writing the attribute by hand:
import { Askable } from '@askable-ui/react';
<Askable meta={{ metric: 'revenue', delta: '-12%', period: 'Q3' }}>
<RevenueChart />
</Askable>import { Pressable, Text } from 'react-native';
import { Askable, useAskable } from '@askable-ui/react-native';
function RevenueCard() {
const { ctx } = useAskable();
return (
<Askable ctx={ctx} meta={{ metric: 'revenue', delta: '-12%', period: 'Q3' }} text="Revenue card">
<Pressable>
<Text>Revenue</Text>
</Pressable>
</Askable>
);
}<Askable :meta="{ metric: 'revenue', delta: '-12%', period: 'Q3' }">
<RevenueChart />
</Askable><Askable meta={{ metric: 'revenue', delta: '-12%', period: 'Q3' }}>
<RevenueChart />
</Askable>Step 2 — Observe the page
One call covers your entire document. The observer automatically picks up dynamically rendered elements via MutationObserver, and it also responds when existing elements gain/lose data-askable or update data-askable-text / data-askable-priority.
import { useAskable } from '@askable-ui/react';
function App() {
const { promptContext } = useAskable(); // starts observing automatically
// ...
}import { useAskable } from '@askable-ui/react-native';
const { promptContext } = useAskable();
// promptContext updates when Askable-wrapped press targets are pressed or long-pressedimport { useAskable } from '@askable-ui/vue';
const { promptContext } = useAskable(); // starts observing on mountimport { createAskableStore } from '@askable-ui/svelte';
const { promptContext, destroy } = createAskableStore();
onDestroy(destroy);import { createAskableContext } from '@askable-ui/core';
const ctx = createAskableContext();
ctx.observe(document);Step 3 — Send context with the question
Use ctx.toAgentRequest() when you want one JSON-ready payload containing the user question, prompt-ready context, current focus, and an optional Context packet:
async function ask(userMessage: string) {
const response = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(await ctx.toAgentRequest(userMessage, {
history: 3,
packet: true,
})),
});
return response.json();
}For a selection composer, keep the packet from region, circle, lasso, or text selection capture and pass it back with contextFromPacket: true:
await ctx.toAgentRequest(userMessage, {
packet: pendingSelectionPacket,
contextFromPacket: true,
sources: ['accounts'],
});When the user clicks a revenue chart and asks "why is this dropping?", promptContext becomes:
User is focused on: metric: revenue, delta: -12%, period: Q3The LLM now has the context to give a precise, relevant answer.
What's next
- How It Works — internals and architecture
- Annotating Elements — all ways to use
data-askable - Prompt Serialization —
toPromptContext()options, token budgets, JSON format - Focus & History — tracking multi-step interactions