Skip to content

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:

bash
npm create @askable-ui/app my-app
cd my-app
npm install
npm run dev

The scaffold gives you a React + Vite dashboard with data-askable annotations, useAskable() already connected, a CopilotKit sidebar, and a local @copilotkit/runtime server.

bash
npm install @askable-ui/react @askable-ui/core
bash
npm install @askable-ui/react-native @askable-ui/core
bash
npm install @askable-ui/vue @askable-ui/core
bash
npm install @askable-ui/svelte @askable-ui/core
bash
npm install @askable-ui/core

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

html
<!-- 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:

tsx
import { Askable } from '@askable-ui/react';

<Askable meta={{ metric: 'revenue', delta: '-12%', period: 'Q3' }}>
  <RevenueChart />
</Askable>
tsx
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>
  );
}
vue
<Askable :meta="{ metric: 'revenue', delta: '-12%', period: 'Q3' }">
  <RevenueChart />
</Askable>
svelte
<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.

tsx
import { useAskable } from '@askable-ui/react';

function App() {
  const { promptContext } = useAskable(); // starts observing automatically
  // ...
}
ts
import { useAskable } from '@askable-ui/react-native';

const { promptContext } = useAskable();
// promptContext updates when Askable-wrapped press targets are pressed or long-pressed
ts
import { useAskable } from '@askable-ui/vue';

const { promptContext } = useAskable(); // starts observing on mount
ts
import { createAskableStore } from '@askable-ui/svelte';

const { promptContext, destroy } = createAskableStore();
onDestroy(destroy);
ts
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:

ts
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:

ts
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: Q3

The LLM now has the context to give a precise, relevant answer.

What's next

Released under the MIT License.