Shared State

Shared State

Prerequisite

This page assumes you’ve already initialized your Agent (Embedded | Overlay).

Overview

Shared State creates a two-way synchronization between your application's UI state (like a form or settings panel) and the AI agent. This powerful feature allows the agent to both read the current state of your UI in real-time and write changes back to it.


API Reference

The entire process is managed by two main methods on the agent instance.

shareState(key, state, handler)

This is the core method for establishing and updating the synchronized state. It should be called once on initialization and then again every time the user-side state changes.

ParameterTypeRequiredDescription
keystringYesA unique string identifier for this piece of state (e.g., "contact_form").
stateobjectYesA snapshot of the current UI state object (e.g., { name: "", email: "" }).
handler(key: string, nextState: any) => voidNoCrucial for two-way sync. This parameter is optional, but required to allow the agent to push updates back to your UI.

clearState(key)

Tells the agent to stop tracking a piece of state. This is critical for cleanup when a component unmounts or the user navigates away, preventing memory leaks.

ParameterTypeRequiredDescription
keystringYesThe unique string identifier for the state you wish to clear.

React + TypeScript Example

This example shows how to synchronize a React form component's state with the agent using hooks.

import { useEffect, useRef, useState } from "react";

type FormState = {
  name: string;
  email: string;
  company?: string;
};

interface Props {
  agentKey: string;
}

export default function SharedStateForm({ agentKey }: Props) {
  // 1. Local UI state is kept minimal.
  const [form, setForm] = useState<FormState>({ name: "", email: "", company: "" });

  // 2. The agent instance is created once and stored in a ref.
  const agentRef = useRef<any | null>(null);
  const stateKey = "contact_form";

  // 3. `useEffect` handles the entire lifecycle: setup, subscription, and cleanup.
  useEffect(() => {
    // Initialize the agent
    agentRef.current = window.eucera?.agent(agentKey);

    // Agent -> UI: Define the handler to receive updates FROM the agent
    const handleStateChange = (key: string, nextState: unknown) => {
      if (key === stateKey) {
        setForm(nextState as FormState); // Update local state
      }
    };

    // Initial sync: Register the state key, initial data, and the handler
    agentRef.current?.shareState(stateKey, form, handleStateChange);

    // Cleanup function: Tell the agent to stop tracking on unmount
    return () => {
      agentRef.current?.clearState(stateKey);
      agentRef.current = null;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [agentKey]);

  // 4. UI -> Agent: Call this on user input to keep the agent's snapshot fresh.
  const updateField = <K extends keyof FormState>(key: K, value: FormState[K]) => {
    const next = { ...form, [key]: value };
    setForm(next);
    // Send the fresh snapshot to the agent
    agentRef.current?.shareState(stateKey, next);
  };

  // 5. Render your form inputs and call updateField on change.
  return <>...</>;
}

Vanilla JS Example

This example demonstrates how to synchronize standard HTML form inputs without a framework.

<script>
  // 1. Create the agent instance ONCE.
  const agentKey = "YOUR_AGENT_KEY";
  const agent = window.eucera?.agent(agentKey);

  // 2. Choose a stable key for this piece of state.
  const stateKey = "shipping_address";

  // 3. Create helper functions to read from and write to the DOM.
  const readUI = () => ({
    fullName: document.getElementById("fullName")?.value || "",
    street: document.getElementById("street")?.value || "",
    city: document.getElementById("city")?.value || "",
    postal: document.getElementById("postal")?.value || "",
  });

  const writeUI = (next) => {
    if (!next || typeof next !== "object") return;
    Object.entries(next).forEach(([k, v]) => {
      const el = document.getElementById(k);
      if (el) el.value = v ?? "";
    });
  };

  // 4. Agent -> UI: This handler listens for agent-driven updates and writes them to the DOM.
  const handleStateChange = (key, nextState) => {
    if (key === stateKey) {
      writeUI(nextState);
    }
  };

  // 5. On page load, perform the initial sync.
  agent?.shareState(stateKey, readUI(), handleStateChange);

  // 6. UI -> Agent: Add event listeners to send updates to the agent on user input.
  ["fullName", "street", "city", "postal"].forEach((id) => {
    const el = document.getElementById(id);
    if (!el) return;
    el.addEventListener("input", () => agent?.shareState(stateKey, readUI()));
  });

  // 7. Use `beforeunload` to clean up the state.
  window.addEventListener("beforeunload", () => agent?.clearState(stateKey));
</script>