Skip to content

4. Context state

Context is a free-form Record<string, unknown> that the client mirrors to the server. The autopilot sees it on every turn — it is the right place for "what is the user looking at right now".

For our weather assistant, we want the autopilot to know the currently selected city without the user having to repeat it.

Watch the input and update context

vue
<!-- src/App.vue -->
<script setup lang="ts">
import { ref, watch } from 'vue';
import { useAutopilotStore } from '@llmor/autopilot-vue';
import { client } from './autopilot';

const store = useAutopilotStore();
const city = ref('Berlin');

watch(
  city,
  (value) => {
    client.updateContext({ selected_city: value });
  },
  { immediate: true },
);
</script>

<template>
  <main>
    <h1>Weather assistant</h1>
    <p>Status: <strong>{{ store.connectionStatus }}</strong></p>
    <label>
      City:
      <input v-model="city" />
    </label>
  </main>
</template>

Now any time the user types, the autopilot sees the new city on its next turn. If they ask "What's it like today?" the server already has selected_city to work with.

Three ways to write context

ts
client.setContext({ a: 1, b: 2 });          // replace the whole context
client.updateContext({ b: 3, c: 4 });       // shallow merge → { a:1, b:3, c:4 }
client.mergeContext({ nested: { x: 1 } });  // deep merge

All three go through the same debounced JSON Patch pipeline (100 ms). If you need to flush before navigating away:

ts
client.flushContextSync();

Mutate the store's context directly

The Pinia store exposes context as a plain writable reactive object. Mutate it directly and a deep watcher auto-syncs the change to the client:

ts
const store = useAutopilotStore();
store.context.selected_city = 'Lisbon'; // direct mutation
store.context.filters.region = 'EU';    // nested mutations work too
delete store.context.selected_city;      // and deletions

Convenience actions do the same thing if you prefer method calls:

ts
store.setContextProperty('selected_city', 'Lisbon');
store.updateContextProperties({ a: 1, b: 2 });
store.clearContext();

Read store.context in your templates. Everything ends up calling the same setContext under the hood (debounced 100 ms) — pick one style and stay consistent.

Next: drop in the AutopilotBar so the user can actually talk to the assistant.