Connect OneTwoAgent to your app
Add the OneTwoAgent Widget to your application, recognize signed-in customers securely, and keep each customer's conversation history connected to their account.
Quick start
- 1Connect your project with the OneTwoAgent CLI.
- 2Ask your coding agent to integrate OneTwoAgent.
- 3Sign in to your application and test the Widget with a real user.
- Recommended setup: use the OneTwoAgent CLI with your coding agent.
- For most applications, you do not need to build the signed-in customer integration manually.
1) Open Widget settings
In OneTwoAgent, open Channels>Widget>Install & Connect.
- Make sure you are inside the OneTwoAgent business you want to connect to your application.
- The connection belongs to the currently selected business and its Widget.
2) Run the OneTwoAgent CLI
Open a terminal in the root directory of the application you want to integrate, then run the setup command below. The CLI opens OneTwoAgent in your browser and starts a temporary secure connection with the terminal on your computer.
What the CLI does
- Connects the current project to your selected OneTwoAgent business.
- Creates or rotates the Widget Identity Secret when required.
- Stores that secret in a server-side environment file in your project.
- Writes non-secret OneTwoAgent project metadata to .onetwoagent.json.
- Installs the OneTwoAgent coding-agent skill into the project.
Node.js requirement
The OneTwoAgent CLI currently requires Node.js 20 or newer to run. Your application itself does not have to use Node.js.
- For example, your application may use Django, Rails, Laravel, Go, Java, .NET or another backend.
- Node.js is only required for running the CLI setup command.
npx -y @onetwoagent/cli@latest init --browser3) Approve the connection in OneTwoAgent
After the CLI starts, your browser opens a OneTwoAgent connection page titled Connect OneTwoAgent CLI. Click Connect CLI. If this business already has a Widget Identity Secret, you may instead see Rotate secret & connect.
When should I rotate the secret?
- You intentionally want to reconnect the application.
- The existing credential may have been exposed.
- The application should stop using the previous server credential.
- Rotating the secret invalidates the previous Widget Identity Secret for new identity-token exchanges. After rotation, your application must use the new secret.
- When the connection succeeds, the browser shows: Connected - you can return to your terminal.
4) Integrate with your coding agent
Open your coding agent in the same project and send exactly:
- The OneTwoAgent skill installed by the CLI tells the coding agent how to inspect your application and adapt the integration to the framework and authentication system that already exist.
What the coding agent should do
- Inspect the project's framework and router.
- Locate the application's existing authentication/session system.
- Find the stable server-side user ID and email.
- Install the OneTwoAgent Widget once in the application shell or global layout.
- Add one server endpoint that exchanges the authenticated customer for a short-lived OneTwoAgent identity token.
- Call window.OneTwoAgent.identify(token) after the user is authenticated.
- Call window.OneTwoAgent.reset() when the user logs out.
- Refresh the identity when the Widget emits otw:identity:required.
- OneTwoAgent does not replace your authentication system. The integration must reuse the login, session and user model your application already has.
Integrate OneTwoAgentHow signed-in customer identity works
The identity flow is intentionally split between your server and the browser.
- Your long-lived Widget Identity Secret stays on your server.
- The browser receives only a short-lived identity token issued by OneTwoAgent.
- This means the browser never needs access to your permanent OneTwoAgent server credential.
Your application
|
| signed-in user
| stable ID + email
v
Your server
|
| ONETWOAGENT_WIDGET_IDENTITY_SECRET
v
OneTwoAgent API
|
| short-lived identity token
v
Browser
|
v
window.OneTwoAgent.identify(token)
|
v
Customer's OneTwoAgent conversationAnonymous visitors vs signed-in customers
The Widget can work with both anonymous website visitors and authenticated application users.
Anonymous visitor
- Can use the Widget normally.
- Receives a Widget conversation.
- Is not connected to a known account inside your application.
- Relies on the Widget's browser session for anonymous continuity.
Signed-in customer
- Is identified using your application's own stable user ID.
- Can provide trusted email and optional name from your authenticated server session.
- Receives a conversation associated with that application identity.
- Can return later and recover their own conversation.
- Is isolated from conversations belonging to other signed-in users.
- You can install the Widget without enabling logged-in customer identity.
- User B must never receive User A's conversation history.
User A logs in
-> conversation A
User A logs out
User B logs in
-> fresh conversation B
User B logs out
User A logs in again
-> conversation A returnsSupported frameworks and authentication systems
The OneTwoAgent signed-in customer integration is framework-agnostic. Your application needs two capabilities: your server can determine which user is currently authenticated, and that user has a stable internal identifier and an email address.
Common application stacks
This is not an exhaustive list.
- Next.js / React
- Remix
- Express
- Fastify
- Django
- Flask
- FastAPI
- Ruby on Rails
- Laravel / PHP
- Go
- Java / Spring
- ASP.NET
- other applications with a web frontend and server-side authentication
Common authentication systems
The coding agent should detect which authentication system your project already uses. It should not install a second authentication system for OneTwoAgent.
- Auth.js / NextAuth
- Clerk
- Supabase Auth
- Firebase Auth
- custom JWT sessions
- HTTP-only cookie sessions
- server-side session stores
- another existing application authentication system
Can I use signed-in identity with a static website?
A purely static frontend cannot safely hold the long-lived Widget Identity Secret. The secret must remain server-side.
- A static website can still use the normal anonymous OneTwoAgent Widget.
- To recognize signed-in customers, your application needs a server-side or trusted backend function capable of authenticating the current user, reading their stable ID and email, and calling the OneTwoAgent identity-token API securely.
Files created during setup
The CLI writes two different kinds of project configuration. They have very different security properties.
.onetwoagent.json
This file contains no long-lived secret. It tells the coding agent and integration which OneTwoAgent business, Widget and API endpoint this project belongs to.
businessId
The OneTwoAgent business connected to this project.
publicId
The public Widget identifier used when loading the Widget. This value is safe to use in browser-visible Widget installation code.
apiBaseUrl
The OneTwoAgent API origin used by your server integration.
{
"version": 1,
"businessId": "your-business-id",
"publicId": "your-widget-public-id",
"apiBaseUrl": "https://api.onetwoagent.com"
}Widget Identity Secret
The CLI also stores the value below. This value is secret. It must remain on the server. Treat it like another production API credential.
Never expose it through public environment variables
Do not expose it through your framework's equivalent public/client environment system.
- NEXT_PUBLIC_*
- VITE_*
- PUBLIC_*
- Never expose it in browser JavaScript, HTML, localStorage, sessionStorage, browser cookies, URLs, query parameters, logs, analytics events, or client-side error messages.
- Never commit the Widget Identity Secret to Git.
ONETWOAGENT_WIDGET_IDENTITY_SECRET=...Manual integration
The CLI + coding-agent flow is recommended. The manual architecture is the same regardless of framework.
- Use the manual integration when your development environment cannot run a coding agent.
- Use it when your team prefers to implement the integration directly.
- Use it when you need full manual control over the integration.
1) Install the Widget
Add the OneTwoAgent Widget once in your global application shell or shared layout.
- YOUR_WIDGET_PUBLIC_ID comes from .onetwoagent.json or Widget Settings.
- Do not create a different Widget instance for every user.
- Do not manually manage OneTwoAgent conversation IDs. The Widget owns its own conversation state.
<script
src="https://onetwoagent.com/widget/v1.js"
data-id="YOUR_WIDGET_PUBLIC_ID"
defer>
</script>2) Create a server identity endpoint
Your application needs a server-only endpoint that reads the currently authenticated user using your existing auth system, returns 401 when no user is authenticated, extracts a stable user ID and email, and exchanges them with OneTwoAgent for a short-lived identity token.
- The exact server API syntax depends on your framework. The security model does not.
const user = await getCurrentAuthenticatedUser()
if (!user) {
return response(401)
}
const upstream = await fetch(
'https://api.onetwoagent.com/api/widget/identity/token',
{
method: 'POST',
headers: {
Authorization:
`Bearer ${process.env.ONETWOAGENT_WIDGET_IDENTITY_SECRET}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
externalUserId: String(user.id),
email: user.email,
name: user.name,
}),
}
)
return upstream.json()externalUserId
externalUserId must be your application's stable internal customer/user identifier.
Good examples
- database user UUID
- database user numeric ID
- stable account ID
- stable customer ID
Avoid
- temporary session ID
- browser-generated random ID
- access-token ID
- temporary request ID
- If your application already has a stable database user ID, use it.
- Do not replace an existing stable ID with the email address.
Email is required for signed-in customer identity. Read it from the authenticated server-side session or user record.
- Do not accept an arbitrary email supplied directly by the browser without authenticating it first.
name
Name is optional. If your authenticated user already has a name, you may send it to OneTwoAgent.
3) Identify the customer in the browser
After your own application confirms that the browser belongs to an authenticated user, request a short-lived identity token from your server endpoint.
- Do not store the identity token yourself unless your integration has a specific reason to do so.
- The Widget manages its own conversation state.
const response = await fetch('/api/onetwoagent/identity', {
credentials: 'include',
})
if (!response.ok) return
const { token } = await response.json()
await window.OneTwoAgent.identify(token)4) Reset identity on logout
When your application logs the customer out, reset the Widget identity.
- Call reset() synchronously as part of the logout lifecycle.
- This ensures that the next visitor cannot inherit the previous signed-in customer's Widget identity.
- The application's own logout should continue normally.
window.OneTwoAgent.reset()5) Refresh identity when requested
Identity tokens are short-lived. The Widget emits otw:identity:required when it needs a fresh identity token.
- Do not create an aggressive retry loop. If refreshing fails, allow the next natural authentication or Widget event to try again.
- Do not log the application user out simply because OneTwoAgent identity refresh failed.
window.addEventListener('otw:identity:required', async () => {
if (!currentUserIsAuthenticated()) return
const response = await fetch('/api/onetwoagent/identity', {
credentials: 'include',
})
if (!response.ok) return
const { token } = await response.json()
await window.OneTwoAgent.identify(token)
})6) Switching accounts without a page reload
Some applications can switch from one user or account to another without fully reloading the page. After the new application session becomes active, identify the new account.
- Do not merge the old customer's Widget history into the new customer. OneTwoAgent resolves the appropriate customer conversation from the new identity.
await window.OneTwoAgent.identify(tokenForNewUser)Avoid stale identity after logout
An asynchronous identity request may still be running when a customer logs out. Your integration should make sure an old identity request cannot complete after logout and identify the previous customer again.
- Your coding agent should handle this lifecycle when adapting the integration to your framework.
identify User A starts
-> User A logs out
-> Widget identity is invalidated/reset
-> old User A request finishes
-> old result must be ignoredControl where the Widget appears
For most applications, install the Widget globally and control visibility from OneTwoAgent. This keeps page-placement decisions in Widget Settings instead of scattering Widget conditions throughout your application code.
- Open Channels>Widget>Advanced -> Where the Widget appears.
- The underlying settings are Allowed Pages and Excluded Pages.
Show the Widget everywhere
Turn Page Restrictions off.
- The Widget appears on every allowed domain.
Page Restrictions: OffHide the Widget from login, registration and checkout
Leave Allowed Pages empty. Add the paths below to Excluded Pages.
- Result: Widget appears on all pages except these excluded paths.
- This is a common configuration for authenticated SaaS applications.
/login
/register
/checkout
/checkout/*Show the Widget only inside the authenticated application
Add the paths below to Allowed Pages and leave Excluded Pages empty.
- Result: Widget appears only on /dashboard and its child pages.
/dashboard
/dashboard/*Allowed Pages
Allowed Pages define where the Widget may appear.
- When Allowed Pages contains values, paths that do not match the list are hidden unless the configuration has another applicable rule.
- If Allowed Pages is empty, the Widget is allowed on all pages except pages explicitly excluded.
/dashboard
/dashboard/*
/products/*Excluded Pages
Excluded Pages define where the Widget must never appear.
- Excluded Pages always win. If a page matches both Allowed Pages and Excluded Pages, the Widget is hidden.
/login
/register
/checkout
/admin/*Wildcard examples
* can match multiple characters.
/products/*
Matches product pages below /products.
/dashboard/*
Matches pages below /dashboard.
/blog/*/comments
Matches nested blog-comment URLs matching that structure.
Allowed Domains
Allowed Domains and Page Restrictions solve different problems.
Allowed Domains
Answers: which websites are trusted to load this Widget? Use Allowed Domains to prevent your Widget installation from being reused on unrelated websites.
- example.com
- www.example.com
- app.example.com
Allowed Pages / Excluded Pages
Answers: where inside an allowed website should the Widget appear?
- Example: allowed domain app.example.com, excluded page /login -> the Widget is trusted on app.example.com, but hidden when the visitor opens /login.
Logout and conversation continuity
Signed-in identity connects Widget conversations to the authenticated customer.
- This lets the same application account continue its OneTwoAgent conversation across visits without exposing another customer's conversation.
User A logs in
-> OneTwoAgent identifies User A
-> User A conversation appears
User A refreshes
-> User A conversation remains
User A logs out
-> Widget identity resets
User B logs in
-> User B gets their own conversation
User B logs out
User A logs in again
-> User A's previous conversation returnsSecurity model
The most important security boundary is simple.
Server-only
This is a long-lived server credential. Keep it private.
- ONETWOAGENT_WIDGET_IDENTITY_SECRET
Browser-safe
The public Widget ID is intentionally public. The short-lived identity token is issued by OneTwoAgent for the authenticated user.
- Widget publicId
- short-lived OneTwoAgent identity token
- Never place ONETWOAGENT_WIDGET_IDENTITY_SECRET in NEXT_PUBLIC_*, VITE_*, PUBLIC_*, browser JavaScript, HTML, localStorage, sessionStorage, browser cookies, URLs, query strings, logs, or client analytics.
- Your server identity endpoint is the only part of the customer application that needs this secret.
Rotating the Widget Identity Secret
Widget Settings allows you to rotate the identity secret.
- Rotate when you suspect the secret was exposed.
- Rotate when you intentionally reconnect the integration.
- Rotate when you want the previous credential to stop working.
- After rotation: the previous server credential is no longer valid for new identity-token exchanges; your application needs the new credential; reconnect the project through the OneTwoAgent CLI or update the server environment securely.
- Do not rotate casually on every deployment. Treat rotation as a credential-management action.
Test your integration
Before considering signed-in identity complete, test with at least two real application accounts.
User A
- Log in as User A
- Open the Widget
- Send a message
- Wait for the reply
- Refresh the page
- User A's conversation is still present
Logout and User B
- Log out User A
- Log in as User B
- Open the Widget
- No User A messages are visible
- Send a message as User B
- Refresh the page
- User B's conversation remains
Return to User A
- Log out User B
- Log in again as User A
- Open the Widget
- User A's previous conversation returns
- User B's messages are not present
- If all checks pass, signed-in identity and conversation continuity are working correctly.
Troubleshooting
Troubleshooting by symptom.
Widget does not appear
- The Widget script is installed.
- The Widget is enabled.
- The current hostname is allowed by Allowed Domains.
- Page Restrictions are configured correctly.
- The current path is not in Excluded Pages.
Widget appears on the login page
- Add the login path to Excluded Pages, for example /login.
- For applications with multiple auth pages: /login, /register, /forgot-password, /reset-password/*
window.OneTwoAgent.identify is unavailable
- Verify widget/v1.js loaded successfully.
- Verify the Widget script is installed once.
- Verify your identify code runs after the Widget has initialized.
- If your framework loads third-party scripts asynchronously, wait until the Widget API is available before calling identify().
Identity endpoint returns 401
- A 401 normally means your own application does not consider the request authenticated.
- Check your application's session cookie, authentication middleware, server session helper, login state.
- Fix the application authentication first.
- Do not bypass your application's authentication just to make OneTwoAgent identity work.
Identity endpoint cannot obtain a OneTwoAgent token
- Check ONETWOAGENT_WIDGET_IDENTITY_SECRET exists in the server environment.
- Check the value belongs to the correct OneTwoAgent business.
- Check the secret was not rotated without updating the application.
- Check .onetwoagent.json points to the intended OneTwoAgent business/API.
- Do not print the secret into logs while debugging.
User B sees User A's conversation
- Stop testing until logout/account-switch handling is corrected.
- Verify that window.OneTwoAgent.reset() runs when User A logs out.
- Make sure an older asynchronous identify() operation cannot finish after logout and identify User A again.
- Expected behavior is strict separation: User A -> conversation A, User B -> conversation B.
Conversation does not return after signing in again
- Check that the same application account uses the same stable externalUserId.
- Do not generate a new external ID for every login session.
- The stable ID should normally be your application's own database user/account ID.
CLI cannot connect to the intended business
- Sign in to OneTwoAgent.
- Switch to the business you want to connect.
- Run the CLI command again.
- Approve the connection in that business.
- The project metadata written by the CLI should represent the intended business and Widget.
Final checklist
Before going live:
- Widget script installed once
- Correct OneTwoAgent business connected
- Allowed Domains configured if needed
- Page visibility configured
- ONETWOAGENT_WIDGET_IDENTITY_SECRET is server-only
- Stable application user ID is used
- Email comes from authenticated server session
- identify(token) runs after authentication
- reset() runs on logout
- Identity refresh event is handled
- User A survives refresh
- User B cannot see User A
- User A history returns when User A signs in again
- Once these checks pass, your application is connected to OneTwoAgent with signed-in customer identity and conversation continuity.
İlgili rehberler
Kanallar, rezervasyonlar, planlama veya otomasyon için sonraki kurulum adımlarına devam edin.
Sık sorulan sorular
Does my SaaS need to use Node.js?
No. Your application can use any web stack that provides a server-side authentication boundary. Node.js 20+ is currently required only to run the OneTwoAgent CLI.
Does OneTwoAgent replace my authentication system?
No. OneTwoAgent uses your existing authenticated user. Your login system remains the authority for deciding who the user is.
Can I use the Widget without logged-in identity?
Yes. The normal Widget works for anonymous visitors without signed-in identity. Logged-in identity is an additional integration for applications that want OneTwoAgent conversations connected to their own user accounts.
Is .onetwoagent.json secret?
No. It contains non-secret project metadata such as the OneTwoAgent business ID, Widget public ID and API base URL. The secret is stored separately, server-only, as ONETWOAGENT_WIDGET_IDENTITY_SECRET.
Can the same customer restore their conversation after returning later?
Yes. When your application identifies the same stable customer again, OneTwoAgent resolves that customer's conversation.
Can two application users see the same Widget history?
They should not. Different stable application user IDs are isolated from each other. If User B sees User A's history, review logout/account-switch integration immediately.
Should I install the Widget only on authenticated pages?
Usually, no. A common setup is to install the Widget globally, then use Page Restrictions in OneTwoAgent to control visibility. This supports anonymous visitors on public pages while still recognizing signed-in customers inside the application. If you want the Widget only inside authenticated application pages, configure Allowed Pages accordingly.
What happens when I rotate the identity secret?
The previous long-lived server credential can no longer be used for new identity-token exchanges. Your application's server environment must be updated with the new secret.
Do I need to store OneTwoAgent identity tokens?
Normally, no. Request a short-lived token when the signed-in customer needs to be identified and pass it to window.OneTwoAgent.identify(token). Let the Widget manage its conversation session.