Use case
Embedded Portal With Page Tools
Embed a Console portal as a chat bubble in your product, sign visitors in with your own identity token, and let the agent act on the page.
- Stack Console (Enterprise) + your web app
- Pattern Chat · Widget
- Read ~6 min
Overview
Your product already knows who the user is. An embedded portal lets that identity flow into a Console agent without a second login, and lets the agent call page tools: functions your page exposes, such as reading the cart or opening a ticket.
Enterprise module
Portals and embedding are part of the enterprise edition and need an enterprise licence. On SaaS the host page must be served over https; http://localhost works as an allowed site only on development and self-hosted installations.
Run the example
Runnable code for this pattern is public on GitHub:
- console-examples /
05-portal-embed-host: A host app that embeds a Console portal as a chat bubble, with signed identity and page tools.
Architecture
Your server signs a short-lived identity token (HS256) for the signed-in user. The claims are iss (exactly the Issuer set on the portal's Embed tab), aud = cognipeer-portal:<portal key>, sub, iat, exp, a fresh jti (a token works once), and optional email, email_verified, name, groups and ctx. The signing secret never leaves the server.
The widget (/api/embed/portal.v1.js on your Console) is mounted in the browser with a getToken callback and the page tools.
Console checks the allowed sites, verifies the token, maps the person to a member, and runs the portal's agent. Page tools run in the visitor's browser and are only offered to agents that have May use the page's tools switched on in the portal.
1. Mint The Token On Your Server
import { SignJWT } from "jose";
export async function mintToken(user: { id: string; email: string; name: string }) {
return new SignJWT({ email: user.email, email_verified: true, name: user.name })
.setProtectedHeader({ alg: "HS256", kid: process.env.EMBED_KEY_ID! })
.setIssuer(process.env.EMBED_ISSUER!)
.setAudience(`cognipeer-portal:${process.env.COGNIPEER_PORTAL}`)
.setSubject(user.id)
.setIssuedAt()
.setExpirationTime("120s")
.setJti(crypto.randomUUID())
.sign(new TextEncoder().encode(process.env.EMBED_SECRET!));
}2
3
4
5
6
7
8
9
10
11
12
13
Return a new token on every request to your token route. Do not cache it, or Console rejects the second exchange as replayed.
2. Declare The Page Tools In Console
On the portal's Embed tab, add each tool under Tools in your page with a description, an input schema, Wait for the page, and Ask the person first. Use Ask the person first for any tool that changes the page. Then turn on May use the page's tools for the agent in the portal's Chat features tab, and give the agent instructions that say when to use each tool.
3. Mount The Widget
The example mounts CognipeerPortal in bubble mode with getToken, the tool handlers, optional context, event listeners, and a logout() call when the user signs out. Handlers should validate their arguments before touching the page.
Security Notes
A page tool result is typed in the person's browser, so the agent treats it as untrusted. Never return an authorization decision from a tool. Put trusted facts in the signed ctx claim and enforce permissions on your server. The context passed to mount is unsigned page information, not identity.
Result
An in-product assistant that knows the signed-in user and can act on the current page, with approvals where it matters.
Related use cases
Agent Approvals Through Webhooks
Pause an agent before it runs a risky tool, get a signed webhook, and approve or deny from your own backend with the client API.
Let Users Choose The Agent's Model
Offer a main model plus additional models on one agent and let the caller, or a chat UI model picker, choose which one answers.
Customer Support Bot
Deploy conversational AI with streaming responses, human-in-the-loop escalation, guardrails, and tool transparency.
See every pattern on the use case index, or browse all Cognipeer libraries.

