Inspiration

Every company's onboarding is the same story: HR submits a ticket, someone manually invites the new hire to GitHub, another person adds them to Slack, a third sends a welcome email, and by the time calendar invites go out it's day two. It's repetitive, error-prone, and nobody owns it end-to-end.

We wanted to fix that with a single system that handles all of it autonomously — while keeping a human in the loop for the one thing that actually needs approval: production access.

What it does

Onboard is a multi-agent AI system that provisions a new hire across four platforms simultaneously the moment HR submits a form:

  • GitHub — Resolves the hire's username, invites them to the org, and uses GPT-4o-mini to select which repos are relevant to their role from the org's actual repo list
  • Slack — Sends a workspace invite, adds them to HR-specified channels, and lets the LLM suggest additional channels based on their role and team
  • Gmail — Generates a fully personalised HTML welcome email using the hire's role, team, and start date — not a template, a real message
  • Google Calendar — Plans 3 role-specific onboarding meetings using LLM reasoning, checks freebusy availability, and sends calendar invites

All four agents run in parallel via LangGraph. Every action produces an immutable audit log showing exactly which credential was used (Token Vault vs fallback), what the LLM reasoned, and what happened.

For production system access, the pipeline pauses and sends a push notification to the manager's Auth0 Guardian app via CIBA (Client-Initiated Backchannel Authentication). The agent waits, and only continues once the manager taps Allow.

How we built it

  • LangGraph — Parallel fan-out StateGraph with merge reducers for concurrent agent execution
  • Auth0 — Session auth (Next.js SDK), Token Vault for scoped runtime credentials, CIBA for human-in-the-loop approval
  • GPT-4o-mini via LangChain — Per-agent reasoning: repo selection, channel suggestions, email generation, meeting planning
  • Next.js 16 (App Router) — Full-stack, API routes, server components, proxy.ts middleware
  • Octokit, Slack Web API, Gmail API, Google Calendar API — Direct platform integrations
  • Vercel — Deployment

Challenges we ran into

Token Vault activation was the hardest part. The SDK returns federated_connection_refresh_token_not_found — an error that sounds like a user-level scope problem. It isn't. It means Token Vault requires a tenant-level feature activation that isn't available through the self-serve dashboard and isn't documented anywhere in the setup guide. We spent two days tracing through oauth4webapi source code, testing scope combinations, and debugging JWE vs JWS token format issues before discovering the real cause.

CIBA required careful polling logic — the agent needed to pause mid-graph, poll Auth0's token endpoint, handle timeouts gracefully, and resume the LangGraph state on approval.

Parallel agent state merging in LangGraph required custom reducers so that concurrent audit log writes from four agents didn't overwrite each other.

Accomplishments

  • All four agents running in parallel and completing end-to-end on the hosted deployment
  • CIBA approval gate fully functional — push notification to Auth0 Guardian, agent pauses and resumes
  • LLM reasoning that selects real org repos, suggests real channel names, writes real emails
  • A clean audit trail showing token source and LLM reasoning for every single action

What we learned

Auth0's Token Vault and CIBA are the right primitives for agentic AI systems. Scoped, just-in-time credentials with a human approval gate is exactly the security model agents need. The concept is sound — the gap is purely in activation UX and documentation.

What's next

  • Full Token Vault activation once tenant support is available
  • Per-org configuration so the system can onboard into any company's GitHub/Slack/Google
  • A persistent job store (database) to replace the current in-memory store
  • Step-up authentication for sensitive repo access requests

Bonus Blog Post

Two Days, One Missing Line of Documentation

When I started building Onboard, Token Vault felt like the perfect solution. My agents needed to call GitHub, Slack, Gmail, and Google Calendar on behalf of users — and storing OAuth refresh tokens in my own database felt wrong. Token Vault promised scoped, just-in-time credentials managed by Auth0. I was sold.

Then I tried to make it work.

The first sign of trouble was subtle. After configuring the Google social connection, setting "Authentication and Connected Accounts" mode, requesting offline_access, forcing prompt: consent — everything the docs described — my agents were still hitting the fallback credential path. The SDK was throwing federated_connection_refresh_token_not_found.

I assumed I'd misconfigured something. I spent hours on scopes. I tried adding create:me:connected_accounts to the login flow — Auth0 silently dropped it. I traced through the @auth0/nextjs-auth0 source code into oauth4webapi, where I found WWWAuthenticateChallengeError being thrown when the My Account API returned a 401. I built a server-side debug endpoint. I discovered the session token was JWE format, which the My Account API rejects outright. I tried a fresh login. I tried the built-in /auth/connect endpoint.

Nothing worked — and at no point did Auth0 tell me why.

Eventually I found it: Token Vault requires a tenant-level feature activation that doesn't exist in the self-serve dashboard. One sentence. Missing from every page of the documentation.

I shipped Onboard with fallback credentials and a note in every audit log entry: "configure Token Vault connection in Auth0 Dashboard to upgrade."

The architecture is right. Token Vault is the correct primitive for agentic systems. But that missing sentence cost me two days — and it's the first thing I'd fix.

Built With

Share this project:

Updates