ConnectedAgent is a powerful showcase of Descope's Outbound Apps, enabling secure, AI-driven interactions with CRM systems and business tools. Itβs designed as both a reference implementation and a customizable foundation for production apps.
ConnectedAgent is a modern, secure, AI-driven integration platform designed to help users connect to their favorite business tools, interact with them through natural language, and perform real-time actionsβlike scheduling meetings, managing contacts, and analyzing dealsβall from one intelligent interface.
At its core, ConnectedAgent is a reference implementation for developers building:
- AI-powered CRM assistants
- Secure third-party OAuth integrations
- Tool-calling agents that manage user tokens and scopes
It leverages Descopeβs Outbound and Inbound Apps architecture, enabling secure identity and access delegation to and from third-party platforms.
- π€ AI Conversations β Natural language interface for CRM workflows
- π OAuth Integration β Secure connections to external services
- π§ Progressive Scoping β Request only the permissions you need, when you need them
- π Analytics β Monitor usage and performance
- π οΈ Extensibility β Easily add your own tools and services
- π 10xCRM (via Inbound Apps)
- π Google Calendar
- π₯ Google Meet
- π User Authentication via Descope
- π OAuth Token Handling with Descope Outbound Apps
- Outbound Apps β Securely connect to third-party tools
- Inbound Apps β Accept connections from apps like 10xCRM
- Tool Registry β Modular architecture for dynamic tool loading
ConnectedAgent actually demonstrates both Outbound and Inbound Apps with Descope, but with Inbound Apps from the perspective of the OAuth client.
For more context on what each of these are, here is a brief overview:
Let your app connect to third-party services on behalf of the user.
- Example: Get a userβs Google Calendar events
- Securely stores and refreshes tokens
- Grants only requested scopes
Let third-party apps connect to you using OAuth.
- Example: Your application integrating with ConnectedAgent as an OAuth authorization provider that we can "connect" to.
- You define the scopes, consent screen, and token logic
- You enable AI agents to "use" your APIs with proper scoping and authorization
Use 10xCRM as a model to:
- Set up OAuth endpoints
- Handle access/refresh tokens
- Validate and enforce scopes
- Manage user consent and authorization flows
- Node.js 18+
- PostgreSQL
- Descope account
git clone https://github.com/descope-sample-apps/connected-agent.git
cd connected-agent
npm installcp .env.example .env.localUpdate .env.local:
NEXT_PUBLIC_DESCOPE_PROJECT_ID=your-project-id
DESCOPE_MANAGEMENT_KEY=your-key
DESCOPE_BASE_URL=https://api.descope.com
OPENAI_API_KEY=your-openai-api-key
NEXT_PUBLIC_SEGEMENT_WRITE_KEY=your-segment-key
NEXT_PUBLIC_APP_URL=http://localhost:3000
DATABASE_URL=your-database-urlnpm run migratenpm run devOnce you've set everything up and tested it, you can easily deploy with our one click deploy buttons at the top of this README to either Vercel or Netlify.
The great thing about this sample app, is that it's very extensible. As an example, we've also described how you can fork this repo and build your own custom tools, to be used in conjunction with Descope Outbound Apps.
// lib/ai/tools/my-tool.ts
import { z } from "zod";
export function myTool({ userId, dataStream }) {
return {
description: "Your tool description",
parameters: z.object({
param1: z.string().describe("Parameter description"),
}),
execute: async ({ param1 }) => {
// Tool logic
return { success: true, result: "Tool result" };
},
};
}// lib/ai/tool-registry.ts
import { myTool } from "./tools/my-tool";
export const toolRegistry = {
myTool,
// ... other tools
};// lib/oauth-utils.ts
export const DEFAULT_SCOPES = {
"my-service": ["required.scope1", "required.scope2"],
};// lib/ai/tools/custom-crm.ts
import { z } from "zod";
import { getOAuthToken } from "@/lib/oauth-utils";
export function customCrmTool({ userId, dataStream }) {
return {
description: "Interact with your custom CRM system",
parameters: z.object({
action: z.enum(["create", "read", "update", "delete"]),
entity: z.string().describe("CRM entity like contact or deal"),
data: z.record(z.any()).optional(),
}),
execute: async ({ action, entity, data }) => {
const token = await getOAuthToken(userId, "custom-crm");
const response = await fetch(
`${process.env.CUSTOM_CRM_API_URL}/${entity}`,
{
method: action.toUpperCase(),
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: data ? JSON.stringify(data) : undefined,
}
);
if (!response.ok) {
throw new Error(
`Failed to ${action} ${entity}: ${response.statusText}`
);
}
return {
success: true,
result: await response.json(),
};
},
};
}import { customCrmTool } from "./tools/custom-crm";
export const toolRegistry = {
customCrm: customCrmTool,
// other tools...
};export const DEFAULT_SCOPES = {
"custom-crm": ["crm.read", "crm.write"],
};We welcome PRs! To contribute:
git clone https://github.com/yourusername/connected-agent.git
cd connected-agentgit checkout -b feature/my-feature- Use TypeScript
- Maintain code style
- Add tests
- Update docs
git commit -m 'feat: my feature'
git push origin feature/my-feature- Describe your changes
- Link related issues
- Include screenshots for UI changes
- Ensure tests pass
This project is licensed under the MIT License.
- π Documentation
- π File an Issue
- π¬ Email: support@descope.com