Agent SDK

Use the web embed widget

Ship a working web agent quickly with EmcyChat from react-embed, then layer in same-user identity and host context.

10 sections

@emcy/agent-sdk/react-embed is the fastest way to put an Emcy agent into a web app.

Use it when:

  • you want a working embed quickly
  • you are fine with Emcy owning the widget UI
  • you do not need a fully custom transcript, dock, or systems panel

Install#

BASH
npm install @emcy/agent-sdk

Minimal example#

TSX
import { EmcyChat } from "@emcy/agent-sdk/react-embed";
 
export function SupportPanel() {
  return (
    <div style={{ height: 640 }}>
      <EmcyChat
        apiKey="emcy_sk_xxxx"
        agentId="ag_xxxxx"
        mode="inline"
        title="Support Agent"
      />
    </div>
  );
}

Same-user embedded auth#

If one of the agent's attached MCP servers requires user-scoped OAuth, pass the current host user through userIdentity and scope the embed to the current host session with appSessionKey.

TSX
import { EmcyChat } from "@emcy/agent-sdk/react-embed";
 
export function BillingAssistant() {
  return (
    <div style={{ height: 640 }}>
      <EmcyChat
        apiKey={process.env.NEXT_PUBLIC_EMCY_API_KEY!}
        agentId={process.env.NEXT_PUBLIC_BILLING_AGENT_ID!}
        mode="inline"
        title="Billing Agent"
        appSessionKey={session.id}
        userIdentity={{
          subject: session.user.id,
          email: session.user.email,
          organizationId: session.organizationId,
          displayName: session.user.name,
        }}
      />
    </div>
  );
}

Use appSessionKey so the embed does not accidentally reuse persisted MCP auth or resumed conversation state across logout/login boundaries.

Common props#

The most common embed props are:

  • apiKey
  • agentId
  • serviceUrl
  • mode
  • title
  • appSessionKey
  • userIdentity
  • appContext
  • clientTools

Add client tools#

Even with the widget, you can expose client-side actions to the agent.

TSX
const clientTools = {
  refreshInvoices: {
    description: "Refresh the invoice list shown in the current page.",
    parameters: {},
    execute: async () => {
      await refetchInvoices();
      return { success: true };
    },
  },
  openInvoice: {
    description: "Open a specific invoice in the current app.",
    parameters: {
      invoiceId: {
        type: "string",
        description: "Invoice id to open.",
        required: true,
      },
    },
    execute: async ({ invoiceId }) => {
      router.push(`/invoices/${invoiceId}`);
      return { success: true, invoiceId };
    },
  },
};
 
<EmcyChat
  apiKey="emcy_sk_xxxx"
  agentId="ag_xxxxx"
  clientTools={clientTools}
/>

Add app context#

appContext is the right place for lightweight runtime hints about the current page.

TSX
<EmcyChat
  apiKey="emcy_sk_xxxx"
  agentId="ag_xxxxx"
  appContext={{
    currentSurface: "invoice-detail",
    hostRefreshInstruction:
      "After any successful invoice mutation, call refreshInvoices before you answer.",
  }}
/>

Use appContext for dynamic, page-specific hints.

Use the agent system prompt for durable product rules.

Inline mode vs floating mode#

Use:

  • mode="inline" for dashboards, settings pages, or side panels
  • floating mode for support-widget style integrations

If your assistant needs to be deeply integrated into the surrounding product chrome, move to custom React UI instead of forcing the widget to behave like a bespoke shell.

Production checklist#

  • add all production domains to the agent's allowed origins
  • pass userIdentity for same-user OAuth-backed MCP flows
  • pass appSessionKey for correct auth and conversation scoping
  • keep clientTools small and explicit
  • test the same agent both in the playground and in the embed

When to move beyond the widget#

Use a custom UI when you need:

  • a docked assistant
  • your own transcript and systems panels
  • branded approvals and input requests
  • app-native mobile layout
  • assistant state woven into product chrome