3. Registering functions
Functions are how you let the autopilot read or do things on the client. The autopilot decides when to call them; your code defines what they do.
Define a get_weather function
ts
// src/autopilot.ts (extending the previous step)
import { AutopilotClient, setAutopilotClient } from '@llmor/autopilot-core';
export const client = new AutopilotClient();
setAutopilotClient(client);
client.registerFunction({
name: 'get_weather',
description: 'Returns the current weather for a city.',
parameters: {
type: 'object',
properties: {
city: {
type: 'string',
description: 'The city to look up.',
},
},
required: ['city'],
},
handler: async ({ city }: { city: string }) => {
const res = await fetch(
`https://wttr.in/${encodeURIComponent(city)}?format=j1`,
);
if (!res.ok) throw new Error(`weather lookup failed: ${res.status}`);
const data = await res.json();
const current = data.current_condition?.[0];
return {
city,
temperature_c: current?.temp_C,
description: current?.weatherDesc?.[0]?.value,
};
},
});
export async function bootAutopilot() {
await client.connect({
conversationUrl: import.meta.env.VITE_CONVERSATION_URL,
});
}A few things to notice:
parametersis JSON Schema, the same format the autopilot uses on the server side. Keep it strict —requiredis honored.- The handler can be sync or async; the return value is JSON-stringified and sent back to the autopilot.
- Thrown errors do not crash the connection. They are surfaced as a
functionErrorevent and reported to the autopilot as a failed call.
Call it
In the conversation, ask the autopilot something like "What's the weather in Berlin?" — it will invoke get_weather and stream a reply.
You can watch it happen by listening to events:
ts
client.on('functionCall', ({ request }) => {
console.log('autopilot is calling', request.name, request.arguments);
});
client.on('functionSuccess', ({ request, result }) => {
console.log('returned', request.name, result);
});
client.on('functionError', ({ request, error }) => {
console.error('failed', request.name, error);
});Unregister at teardown (optional)
If your function is only relevant on a specific route:
ts
import { onScopeDispose } from 'vue';
import { client } from '@/autopilot';
client.registerFunction({ name: 'get_weather', /* … */ });
onScopeDispose(() => client.unregisterFunction('get_weather'));Registration changes are debounced and synced as JSON Patches at /autopilot/functions.