Embed an Agent on Your Own Site
A hired AI agent does not have to live on a page SpiderPublish serves. It runs just as well on your own site — a React, Next or Vite app, or a hand-written HTML page on your own domain. That is what we call BYOS: Bring Your Own Site.
There are two ways in, and they produce the same agent:
Path | Use it when | You install |
|---|---|---|
React SDK | your site is a React, Next or Vite app |
|
Script tag | anything else — plain HTML, WordPress, Webflow, a template you don't control | one |
Both mount the same in-DOM web component. Neither uses an iframe.
Before you start
You need three things, in this order.
1. A hired agent, and its flow id. Agents are hired from the terminal — there is no "create an agent" screen in the dashboard, by design. See The CLI for the full flow; the short version is:
spideriq agent roster # agents you already own — re-embedding one is free
spideriq agent hire <id> --roster --origin https://your-site.com
spideriq agent list # your agents + the flow id for each2. Your site's origin on the agent's allowed list. This is the single most common reason a correct-looking embed never says anything — see Allow your origin below.
3. The snippet, from the tool that owns it. Never hand-write the embed markup:
spideriq agent embed-snippet <flow_id> --mode inlinePath 1 — the React SDK
Point npm at our registry
@spideriq/agent-react is published to the SpiderIQ registry, not to public npm. Add a scope line to your project's .npmrc before installing, or the install fails with a 404 that looks like the package doesn't exist:
@spideriq:registry=https://npm.spideriq.aiThen install. React 18 or newer is a peer dependency; the handshake package comes along automatically.
npm install @spideriq/agent-reactMount it
import { SpiderAgent } from "@spideriq/agent-react";
export function Support() {
return (
<SpiderAgent
flowId="…your agent flow id…"
apiUrl="https://spideriq.ai"
mode="inline"
/>
);
}That is the whole integration. The component renders a plain host <div> on the server and does every piece of browser work inside an effect, so Next.js and any other server-rendered framework are safe out of the box — no dynamic(..., { ssr: false }) wrapper needed.
Props
Prop | Type | What it does |
|---|---|---|
| string | The agent flow id. Required. |
| string | Origin the agent's configuration is fetched from — |
|
|
|
| object | Colour and shape tokens — see Theming below. |
| string | Heading inside the chat card. |
| string | Sub-heading inside the chat card. |
| boolean | Drop the in-card header entirely. |
| boolean or string | Let the agent read the page it is on. Off unless set — see Page-Grounding. |
| — | Applied to the host wrapper element. |
| function | Called once the agent element is in the page, before the connection settles. |
| function | Called with |
Changing flowId, apiUrl or mode starts a fresh agent. theme, title, subtitle and hideHeaders are read once when the agent mounts — change the component's key if you need to swap them live.
Bring your own interface
If you want the conversation but not our chat card, useSpiderAgent() gives you transport and state only. It mounts a hidden agent that renders nothing.
import { useSpiderAgent } from "@spideriq/agent-react";
function Chat() {
const { state, ready, error, send } = useSpiderAgent({
flowId: "…your agent flow id…",
apiUrl: "https://spideriq.ai",
});
if (error) return <p>The assistant is unavailable right now.</p>;
return (
<>
{state?.messages.map((m, i) => <Bubble key={i} msg={m} />)}
<Composer disabled={!ready} onSubmit={send} />
</>
);
}You get back state (the messages and whether a reply is in flight), ready, error, send, respondToWidget and getState. send does nothing until ready is true, so wiring a form to it early is harmless.
Path 2 — the script tag
Paste the snippet where you want the agent, and load the script once anywhere on the page:
<div data-spiderflow-flow="…your agent flow id…"
data-spiderflow-kind="agent"
data-spiderflow-mode="inline"></div>
<script src="https://embed.spideriq.ai/v1/loader.js" async></script>The loader finds every element carrying data-spiderflow-flow and mounts it. One script tag serves any number of agents on a page.
For a floating assistant instead of an in-page panel, change the mode — the element can then live anywhere, since the agent anchors itself to the page:
<div data-spiderflow-flow="…your agent flow id…"
data-spiderflow-kind="agent"
data-spiderflow-mode="concierge"
data-spiderflow-title="Ask us anything"></div>
<script src="https://embed.spideriq.ai/v1/loader.js" async></script>Attributes
Attribute | What it does |
|---|---|
| The agent flow id. Required. |
| Must be |
|
|
| Heading inside the chat card. |
| Sub-heading inside the chat card. |
| Present to drop the in-card header. |
| Let the agent read the page — see Page-Grounding. |
| Only if you were told to point at a different API origin. |
Allow your origin
The agent will only open a conversation for a browser on an origin you have registered. On any other origin the request to start a session is refused, and the visitor sees an agent that mounts and then stays silent.
Register the origin when you hire:
spideriq agent hire <id> --roster --origin https://your-site.comPoints worth knowing before you debug something else:
One origin is one
scheme://host[:port]— no path.https://www.example.comandhttps://example.comare two origins, and so ishttp://localhost:5173.Add your local development origin too, or the agent will work in production and appear broken on your machine.
Sites you host on SpiderPublish with a verified domain are already covered; this step is for domains we don't serve.
Theming
Pass colour and shape tokens and they are applied to the agent before it starts, so your values win over whatever the agent was configured with:
<SpiderAgent
flowId="…"
apiUrl="https://spideriq.ai"
theme={{ primary: "#e11d48", radius: "12px" }}
/>Short names are the token names without their prefix — primary becomes --opvs-agent-primary. A full custom property name is used exactly as you wrote it, so you can hand it any variable the agent understands.
Because the agent renders in your page rather than in an iframe, it inherits your fonts and sits in your stacking context. That is the point of the in-DOM mount: it looks like part of your site instead of a rectangle bolted onto it.
Where the session token lives
The short-lived session token the agent uses is held in a JavaScript closure and passed straight to the agent element. It is never written into an attribute, into the DOM, into React state or props, or into storage — so it cannot appear in your server-rendered HTML, in a React devtools tree, or in a DOM snapshot. Nothing you paste into your page contains a credential.
The configuration the embed fetches is filtered server-side before it is sent, so it carries identifiers and URLs only.
Check it on your own site
Do these in order — each one rules out the layer below it.
Does the agent appear? If nothing renders, open the console. A 404 on the loader or the package means the script URL or the
.npmrcregistry line is wrong.Does it answer? Send a message and wait for a reply. Silence after a clean mount almost always means the origin is not on the allowed list — check the browser's network tab for the refused session request.
**Does it answer as your agent?** Ask it something only your agent should know. If it answers generically, you are talking to a different flow id than you think.
Does it work on the real domain? Test on the deployed site, not only on localhost — they are different origins, and the allowlist treats them that way.
Good to know
The same agent can sit on several sites. Add each origin; the flow id stays the same.
Re-embedding an agent you already own is free.
spideriq agent rosterlists them; hiring a new one is the billed path.The agent is not in an iframe. It renders inside your page in a shadow root, which is why it can pick up your typography — and why Page-Grounding can let it read the page at all.
Never hand-compose the embed markup. Get it from
spideriq agent embed-snippet— a hand-written attribute that is subtly wrong mounts nothing and reports nothing.
Next steps
Page-Grounding — let the agent read the page a visitor is looking at.
The CLI — hire an agent, allow a domain, list your agents.
MCP Setup — the same actions from an MCP-capable agent.
Agent Embed Protocol — the HTTP calls underneath both install paths, for a native app, a server-side proxy, or debugging.