Add OpenAI Agents example (#447)
Add a TypeScript example showing how to integrate OpenAI Agents with Arcade AI, including basic usage and manual authorization flow.
This commit is contained in:
parent
bbe8cb3478
commit
6921500e3c
8 changed files with 1851 additions and 0 deletions
2
examples/openai-agents-ts/.env.example
Normal file
2
examples/openai-agents-ts/.env.example
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
OPENAI_API_KEY=sk-proj-1234567890
|
||||||
|
ARCADE_API_KEY=arc_1234567890
|
||||||
42
examples/openai-agents-ts/.gitignore
vendored
Normal file
42
examples/openai-agents-ts/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
# Dependencies
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# Build output
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
out/
|
||||||
|
|
||||||
|
# IDE and editor files
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs/
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
coverage/
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
tmp/
|
||||||
|
temp/
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
21
examples/openai-agents-ts/LICENSE
Normal file
21
examples/openai-agents-ts/LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025, Arcade AI
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
158
examples/openai-agents-ts/README.md
Normal file
158
examples/openai-agents-ts/README.md
Normal file
|
|
@ -0,0 +1,158 @@
|
||||||
|
<h3 align="center">
|
||||||
|
<a name="readme-top"></a>
|
||||||
|
<picture>
|
||||||
|
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/ArcadeAI/.github/refs/heads/main/profile/assets/new_arcade_logo_white.svg" width="300">
|
||||||
|
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/ArcadeAI/.github/refs/heads/main/profile/assets/new_arcade_logo_black.svg" width="300">
|
||||||
|
<img alt="Arcade AI Logo" src="https://raw.githubusercontent.com/ArcadeAI/.github/refs/heads/main/profile/assets/new_arcade_logo_black.svg" width="300" >
|
||||||
|
</picture>
|
||||||
|
</h3>
|
||||||
|
<div align="center">
|
||||||
|
<h3>OpenAI Agents + Arcade AI Example</h3>
|
||||||
|
<a href="https://github.com/your-organization/openai-ts/blob/main/LICENSE">
|
||||||
|
<img src="https://img.shields.io/badge/License-ISC-blue.svg" alt="License">
|
||||||
|
</a>
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://docs.arcade.dev" target="_blank">Arcade Documentation</a> •
|
||||||
|
<a href="https://docs.arcade.dev/toolkits" target="_blank">Integrations</a> •
|
||||||
|
<a href="https://github.com/ArcadeAI/arcade-js" target="_blank">Arcade JS Client</a> •
|
||||||
|
<a href="https://platform.openai.com/docs/assistants/tools" target="_blank">OpenAI Agents</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
# OpenAI Agents + Arcade AI
|
||||||
|
|
||||||
|
This TypeScript project demonstrates how to integrate [Arcade AI](https://docs.arcade.dev) with [OpenAI Agents](https://openai.github.io/openai-agents-js/) to create powerful AI agents that can interact with external services. Arcade provides access to a wide range of tools including Gmail, Slack, LinkedIn, and more through its Google toolkit and other integrations.
|
||||||
|
|
||||||
|
The project showcases two approaches:
|
||||||
|
|
||||||
|
- **Basic integration** (`src/index.ts`): Simple one-time execution with Google toolkit
|
||||||
|
- **Authorization handling** (`src/waitForCompletion.ts`): Manual authorization flow management
|
||||||
|
|
||||||
|
For a list of all hosted tools and auth providers, see the [Arcade Integrations](https://docs.arcade.dev/toolkits) documentation.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- [Node.js](https://nodejs.org/en/download/) (v18.20.8 or higher)
|
||||||
|
- [npm](https://www.npmjs.com/) or [pnpm](https://pnpm.io/installation)
|
||||||
|
- [OpenAI API key](https://platform.openai.com/account/api-keys)
|
||||||
|
- [Arcade API key](https://docs.arcade.dev/home/api-keys)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
1. Clone the repository and install dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Set up environment variables:
|
||||||
|
- Create a `.env` file in the root directory
|
||||||
|
- Add your API keys:
|
||||||
|
|
||||||
|
```
|
||||||
|
OPENAI_API_KEY=your_openai_api_key
|
||||||
|
ARCADE_API_KEY=your_arcade_api_key
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Update the user ID placeholder:
|
||||||
|
- In both `src/index.ts` and `src/waitForCompletion.ts`
|
||||||
|
- Replace `<YOUR_SYSTEM_USER_ID>` with your application's user identifier (e.g., email address, UUID, etc.)
|
||||||
|
|
||||||
|
## Basic Usage
|
||||||
|
|
||||||
|
This example creates an AI agent that can read and process your Gmail emails using Arcade's Google toolkit.
|
||||||
|
|
||||||
|
### Simple Execution
|
||||||
|
|
||||||
|
Run the basic example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
This script will:
|
||||||
|
|
||||||
|
1. Initialize the Arcade client
|
||||||
|
2. Fetch available Google toolkit tools (up to 30)
|
||||||
|
3. Convert them to OpenAI Agents compatible format
|
||||||
|
4. Create an agent that can assist with Google API calls
|
||||||
|
5. Ask "What are my latest emails?" and display the result
|
||||||
|
|
||||||
|
### Authorization Flow Example
|
||||||
|
|
||||||
|
For a more robust implementation that handles authorization flows:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev:waitForCompletion
|
||||||
|
```
|
||||||
|
|
||||||
|
This version includes:
|
||||||
|
|
||||||
|
- Automatic authorization detection and handling
|
||||||
|
- Browser-based OAuth flow initiation
|
||||||
|
- Waiting for authorization completion
|
||||||
|
- Automatic retry after successful authorization
|
||||||
|
|
||||||
|
If you haven't authorized Arcade with Google yet, you'll see a message like:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
Please complete the authorization challenge in your browser: https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&client_id=...
|
||||||
|
```
|
||||||
|
|
||||||
|
Visit the provided URL to authorize Arcade with your Google account. The script will automatically detect when authorization is complete and continue execution.
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
openai-ts/
|
||||||
|
├── src/
|
||||||
|
│ ├── index.ts # Basic OpenAI Agents + Arcade integration
|
||||||
|
│ └── waitForCompletion.ts # Manual authorization flow management
|
||||||
|
├── package.json # Dependencies and scripts
|
||||||
|
└── README.md # This file
|
||||||
|
```
|
||||||
|
|
||||||
|
## Available Toolkits
|
||||||
|
|
||||||
|
You can modify the `toolkit` parameter to access different integrations:
|
||||||
|
|
||||||
|
- `"google"` - Gmail, Google Calendar, Google Drive, Google Docs
|
||||||
|
- `"slack"` - Slack messaging and channels
|
||||||
|
- `"github"` - GitHub repositories and issues
|
||||||
|
- `"linkedin"` - LinkedIn posts and connections
|
||||||
|
- And more in [Arcade Integrations](https://docs.arcade.dev/toolkits) documentation
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
To extend or modify the functionality:
|
||||||
|
|
||||||
|
1. **Change the toolkit**: Update the `toolkit` parameter in the `client.tools.list()` call
|
||||||
|
2. **Modify the query**: Change the question asked to the agent in the `run()` function
|
||||||
|
3. **Add custom instructions**: Update the agent's `instructions` parameter for different behaviors
|
||||||
|
4. **Handle different models**: Switch the `model` parameter to use different OpenAI models
|
||||||
|
|
||||||
|
Example customization:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const slackToolkit = await client.tools.list({ toolkit: "slack", limit: 30 });
|
||||||
|
// ... rest of setup
|
||||||
|
|
||||||
|
const slackAgent = new Agent({
|
||||||
|
name: "Slack agent",
|
||||||
|
instructions: "You are a helpful assistant for managing Slack communications.",
|
||||||
|
model: "gpt-4o",
|
||||||
|
tools
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await run(slackAgent, "Send a message to the #general channel");
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Best Practices
|
||||||
|
|
||||||
|
- Never commit your `.env` file to version control
|
||||||
|
- Keep your API keys secure and rotate them regularly
|
||||||
|
- Use appropriate user identification in production
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under the MIT License - see the LICENSE file for details.
|
||||||
1511
examples/openai-agents-ts/package-lock.json
generated
Normal file
1511
examples/openai-agents-ts/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
17
examples/openai-agents-ts/package.json
Normal file
17
examples/openai-agents-ts/package.json
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"name": "openai-ts",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"author": "",
|
||||||
|
"type": "module",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "npx tsx --env-file=.env src/index.ts",
|
||||||
|
"dev:waitForCompletion": "npx tsx --env-file=.env src/waitForCompletion.ts"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@arcadeai/arcadejs": "1.7.0",
|
||||||
|
"@openai/agents": "^0.0.8"
|
||||||
|
}
|
||||||
|
}
|
||||||
40
examples/openai-agents-ts/src/index.ts
Normal file
40
examples/openai-agents-ts/src/index.ts
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
import Arcade from '@arcadeai/arcadejs';
|
||||||
|
import { executeOrAuthorizeZodTool, toZod } from "@arcadeai/arcadejs/lib";
|
||||||
|
import { Agent, run, tool } from '@openai/agents';
|
||||||
|
|
||||||
|
// 1) Initialize Arcade client
|
||||||
|
const client = new Arcade();
|
||||||
|
|
||||||
|
// 2) Fetch Google toolkit from Arcade and prepare tools for OpenAI Agents
|
||||||
|
const googleToolkit = await client.tools.list({ toolkit: "google", limit: 30 });
|
||||||
|
const arcadeTools = toZod({
|
||||||
|
tools: googleToolkit.items,
|
||||||
|
client,
|
||||||
|
userId: "<YOUR_SYSTEM_USER_ID>", // Replace this with your application's user ID (e.g. email address, UUID, etc.)
|
||||||
|
executeFactory: executeOrAuthorizeZodTool,
|
||||||
|
})
|
||||||
|
|
||||||
|
// 3) Convert the tools to a format that OpenAI Agents can use
|
||||||
|
const tools = arcadeTools.map(({ name, description, execute, parameters }) =>
|
||||||
|
tool({
|
||||||
|
name,
|
||||||
|
description: description ?? "",
|
||||||
|
parameters: parameters as any,
|
||||||
|
execute,
|
||||||
|
strict: true,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// 4) Create a new agent with the Google toolkit
|
||||||
|
const googleAgent = new Agent({
|
||||||
|
name: "Google agent",
|
||||||
|
instructions: "You are a helpful assistant that can assist with Google API calls.",
|
||||||
|
model: "gpt-4o-mini",
|
||||||
|
tools
|
||||||
|
});
|
||||||
|
|
||||||
|
// 5) Run the agent
|
||||||
|
const result = await run(googleAgent, "What are my latest emails?");
|
||||||
|
|
||||||
|
// 6) Print the result
|
||||||
|
console.log(result.finalOutput);
|
||||||
60
examples/openai-agents-ts/src/waitForCompletion.ts
Normal file
60
examples/openai-agents-ts/src/waitForCompletion.ts
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
import Arcade from '@arcadeai/arcadejs';
|
||||||
|
import { isAuthorizationRequiredError, toZod } from "@arcadeai/arcadejs/lib";
|
||||||
|
import { Agent, run, tool } from '@openai/agents';
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
// 1) Initialize Arcade client
|
||||||
|
const client = new Arcade();
|
||||||
|
|
||||||
|
// 2) Fetch Google toolkit from Arcade and prepare tools for OpenAI Agents
|
||||||
|
const googleToolkit = await client.tools.list({ toolkit: "google", limit: 30 });
|
||||||
|
const arcadeTools = toZod({
|
||||||
|
tools: googleToolkit.items,
|
||||||
|
client,
|
||||||
|
userId: "<YOUR_SYSTEM_USER_ID_2>", // Replace this with your application's user ID (e.g. email address, UUID, etc.)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 3) Convert the tools to a format that OpenAI Agents can use
|
||||||
|
const tools = arcadeTools.map(({ name, description, execute, parameters }) =>
|
||||||
|
tool({
|
||||||
|
name,
|
||||||
|
description: description ?? "",
|
||||||
|
parameters: parameters as any,
|
||||||
|
execute,
|
||||||
|
errorFunction: (_, error) => { throw error }
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// 4) Create a new agent with the Google toolkit
|
||||||
|
const googleAgent = new Agent({
|
||||||
|
name: "Google agent",
|
||||||
|
instructions: "You are a helpful assistant that can assist with Google API calls.",
|
||||||
|
model: "gpt-4o-mini",
|
||||||
|
tools
|
||||||
|
});
|
||||||
|
|
||||||
|
// 5) Run the agent, if authorization is required, wait for it to complete and retry
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const result = await run(googleAgent, "What are my latest emails?");
|
||||||
|
console.log(result.finalOutput);
|
||||||
|
break; // Exit the loop if the result is successful
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof Error && isAuthorizationRequiredError(error)) {
|
||||||
|
const response = await client.tools.authorize({
|
||||||
|
tool_name: "Google_ListEmails",
|
||||||
|
user_id: "<YOUR_SYSTEM_USER_ID_2>",
|
||||||
|
});
|
||||||
|
if (response.status !== "completed") {
|
||||||
|
console.log(`Please complete the authorization challenge in your browser: ${response.url}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the authorization to complete
|
||||||
|
await client.auth.waitForCompletion(response);
|
||||||
|
console.log("Authorization completed, retrying...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
Loading…
Reference in a new issue