diff --git a/app/en/home/auth-providers/airtable/page.mdx b/app/en/home/auth-providers/airtable/page.mdx new file mode 100644 index 000000000..7687ce499 --- /dev/null +++ b/app/en/home/auth-providers/airtable/page.mdx @@ -0,0 +1,270 @@ +import { Tabs, Callout, Steps } from "nextra/components"; + +# Airtable + +The Airtable auth provider enables tools and agents to call Airtable APIs on behalf of a user. + +## What's documented here + +This page describes how to use and configure Airtable auth with Arcade. + +This auth provider is used by: + +- Your [app code](#using-airtable-auth-in-app-code) that needs to call Airtable APIs +- Or, your [custom tools](#using-airtable-auth-in-custom-tools) that need to call Airtable APIs + +## Use Arcade's Default Airtable Auth Provider + +Arcade offers a default Airtable auth provider that you can use in the Arcade Cloud Platform. In this case, your users will see `Arcade` as the name of the application that's requesting permission. + +If you choose to use Arcade's Airtable auth, you don't need to configure anything. + +## Use Your Own Airtable App Credentials + + + When using your own app credentials, make sure you configure your project to + use a [custom user + verifier](/home/auth/secure-auth-production#build-a-custom-user-verifier). + Without this, your end-users will not be able to use your app or agent in + production. + + +In a production environment, you will most likely want to use your own Airtable app credentials. This way, your users will see your application's name requesting permission. + +Before showing how to configure your Airtable app credentials, let's go through the steps to create an Airtable app. + +## Create an Airtable App + +Follow the documentation on [Airtable Web API](https://airtable.com/developers/web/api/introduction). You will need to create an OAuth integration in your Airtable account. + +When creating your app, use the following settings: + +- Set an appropriate App name and description. This will be visible to your users authorizing access to your app. +- In the **OAuth Settings** section: + - Take note of the **Client ID** and **Client Secret**. + - Add the redirect URL generated by Arcade (see below) to the **Redirect URLs**. +- Configure the appropriate **Scopes** for your application. Common scopes include: + - `data.records:read` - Read records from bases + - `data.records:write` - Create and update records in bases + - `schema.bases:read` - Read base schemas + - `schema.bases:write` - Modify base schemas + +## Configuring your own Airtable Auth Provider in Arcade + + + + +### Configure Airtable Auth Using the Arcade Dashboard GUI + + + +#### Access the Arcade Dashboard + +To access the Arcade Cloud dashboard, go to [api.arcade.dev/dashboard](https://api.arcade.dev/dashboard). If you are self-hosting, by default the dashboard will be available at http://localhost:9099/dashboard. Adjust the host and port number to match your environment. + +#### Navigate to the OAuth Providers page + +- Under the **OAuth** section of the Arcade Dashboard left-side menu, click **Providers**. +- Click **Add OAuth Provider** in the top right corner. +- Select the **Included Providers** tab at the top. +- In the **Provider** dropdown, select **Airtable**. + +#### Enter the provider details + +- Choose a unique **ID** for your provider (e.g. "my-airtable-provider"). +- Optionally enter a **Description**. +- Enter the **Client ID** and **Client Secret** from your Airtable OAuth integration. +- Note the **Redirect URL** generated by Arcade. This must be added to your Airtable OAuth integration's Redirect URLs. + +#### Create the provider + +Hit the **Create** button and the provider will be ready to be used. + + + +When you use tools that require Airtable auth using your Arcade account credentials, Arcade will automatically use this Airtable OAuth provider. If you have multiple Airtable providers, see [using multiple auth providers of the same type](/home/auth-providers#using-multiple-providers-of-the-same-type) for more information. + + + + +## Using Airtable auth in app code + +Use the Airtable auth provider in your own agents and AI apps to get a user-scoped token for the Airtable API. See [authorizing agents with Arcade](/home/auth/how-arcade-helps) to understand how this works. + +Use `client.auth.start()` to get a user token for the Airtable API: + + + + +```python {21-22} +from arcadepy import Arcade + +client = Arcade(base_url="https://api.arcade.dev") # Automatically finds the `ARCADE_API_KEY` env variable + +user_id = "{arcade_user_id}" + +# Start the authorization process +auth_response = client.auth.start( + user_id=user_id, + provider="airtable", + scopes=["data.records:read", "data.records:write"], +) + +if auth_response.status != "completed": + print("Please complete the authorization challenge in your browser:") + print(auth_response.url) + +# Wait for the authorization to complete +auth_response = client.auth.wait_for_completion(auth_response) + +# Do something interesting with the token... +auth_token = auth_response.context.token +``` + + + + + +```javascript {20-21} +import { Arcade } from "@arcadeai/arcadejs"; + +const client = new Arcade({ baseURL: "https://api.arcade.dev" }); // Automatically finds the `ARCADE_API_KEY` env variable + +const userId = "{arcade_user_id}"; + +// Start the authorization process +const authResponse = await client.auth.start(userId, "airtable", { + scopes: ["data.records:read", "data.records:write"], +}); + +if (authResponse.status !== "completed") { + console.log("Please complete the authorization challenge in your browser:"); + console.log(authResponse.url); +} + +// Wait for the authorization to complete +const response = await client.auth.waitForCompletion(authResponse); + +// Do something interesting with the token... +const auth_token = response.context.token; +``` + + + + +You can use the auth token to call the [Airtable Web API](https://airtable.com/developers/web/api/introduction) endpoints to interact with bases, tables, and records. + +## Using Airtable auth in custom tools + +You can author your own [custom tools](/home/build-tools/create-a-mcp-server) that interact with Airtable API. + +Use the `OAuth2()` auth class to specify that a tool requires authorization with Airtable. The authentication token needed to call the Airtable API is available in the tool context through the `context.authorization.token` property. + +```python {9,17} +from typing import Annotated + +import httpx + +from arcade_tdk import ToolContext, tool +from arcade_tdk.auth import OAuth2 + + +@tool(requires_auth=OAuth2(provider_id="airtable", scopes=["data.records:read"])) +async def list_records( + context: ToolContext, + base_id: Annotated[str, "The ID of the base."], + table_id: Annotated[str, "The ID or name of the table."], +) -> Annotated[dict, "List of records"]: + """Retrieves records from an Airtable table.""" + url = f"https://api.airtable.com/v0/{base_id}/{table_id}" + headers = { + "Authorization": f"Bearer {context.authorization.token}", + "Accept": "application/json", + } + + async with httpx.AsyncClient() as client: + response = await client.get(url, headers=headers) + response.raise_for_status() + return response.json() +``` + +Your new tool can be called like demonstrated below: + + + + + If you are self-hosting, change the `base_url` parameter in the `Arcade` constructor to match your Arcade Engine URL. By default, the Engine will be available at `http://localhost:9099`. + + +```python +from arcadepy import Arcade + +client = Arcade(base_url="https://api.arcade.dev") # Automatically finds the `ARCADE_API_KEY` env variable + +USER_ID = "{arcade_user_id}" +TOOL_NAME = "Airtable.ListRecords" + +auth_response = client.tools.authorize(tool_name=TOOL_NAME, user_id=USER_ID) + +if auth_response.status != "completed": + print(f"Click this link to authorize: {auth_response.url}") + +# Wait for the authorization to complete +client.auth.wait_for_completion(auth_response) + +tool_input = { + "base_id": "appXXXXXXXXXXXXXX", + "table_id": "tblXXXXXXXXXXXXXX", +} + +response = client.tools.execute( + tool_name=TOOL_NAME, + input=tool_input, + user_id=USER_ID, +) +print(response.output.value) +``` + + + + + If you are self-hosting, change the `baseURL` parameter in the `Arcade` constructor to match your Arcade Engine URL. By default, the Engine will be available at `http://localhost:9099`. + + +```javascript +import { Arcade } from "@arcadeai/arcadejs"; + +const client = new Arcade({ baseURL: "https://api.arcade.dev" }); // Automatically finds the `ARCADE_API_KEY` env variable + +const USER_ID = "{arcade_user_id}"; +const TOOL_NAME = "Airtable.ListRecords"; + +// Start the authorization process +const authResponse = await client.tools.authorize({ + tool_name: TOOL_NAME, + user_id: USER_ID, +}); + +if (authResponse.status !== "completed") { + console.log(`Click this link to authorize: ${authResponse.url}`); +} + +// Wait for the authorization to complete +await client.auth.waitForCompletion(authResponse); + +const toolInput = { + base_id: "appXXXXXXXXXXXXXX", + table_id: "tblXXXXXXXXXXXXXX", +}; + +const response = await client.tools.execute({ + tool_name: TOOL_NAME, + input: toolInput, + user_id: USER_ID, +}); + +console.log(response.output.value); +``` + + + diff --git a/app/en/home/auth-providers/calendly/page.mdx b/app/en/home/auth-providers/calendly/page.mdx new file mode 100644 index 000000000..aeba5cfec --- /dev/null +++ b/app/en/home/auth-providers/calendly/page.mdx @@ -0,0 +1,266 @@ +import { Tabs, Callout, Steps } from "nextra/components"; + +# Calendly + +The Calendly auth provider enables tools and agents to call Calendly APIs on behalf of a user. + +## What's documented here + +This page describes how to use and configure Calendly auth with Arcade. + +This auth provider is used by: + +- Your [app code](#using-calendly-auth-in-app-code) that needs to call Calendly APIs +- Or, your [custom tools](#using-calendly-auth-in-custom-tools) that need to call Calendly APIs + +## Use Arcade's Default Calendly Auth Provider + +Arcade offers a default Calendly auth provider that you can use in the Arcade Cloud Platform. In this case, your users will see `Arcade` as the name of the application that's requesting permission. + +If you choose to use Arcade's Calendly auth, you don't need to configure anything. + +## Use Your Own Calendly App Credentials + + + When using your own app credentials, make sure you configure your project to + use a [custom user + verifier](/home/auth/secure-auth-production#build-a-custom-user-verifier). + Without this, your end-users will not be able to use your app or agent in + production. + + +In a production environment, you will most likely want to use your own Calendly app credentials. This way, your users will see your application's name requesting permission. + +Before showing how to configure your Calendly app credentials, let's go through the steps to create a Calendly app. + +## Create a Calendly App + +Follow the documentation on [Getting Started with Calendly API](https://developer.calendly.com/getting-started). You will need to register for a developer account. + +When creating your app, use the following settings: + +- Set an appropriate App name and description. This will be visible to your users authorizing access to your app. +- In the **OAuth Settings** section: + - Take note of the **Client ID** and **Client Secret**. + - Add the redirect URL generated by Arcade (see below) to the **Redirect URIs**. +- Configure the appropriate **Scopes** for your application. Common scopes include: + - `default` - Basic access to user information + - Additional scopes as needed for your use case + +## Configuring your own Calendly Auth Provider in Arcade + + + + +### Configure Calendly Auth Using the Arcade Dashboard GUI + + + +#### Access the Arcade Dashboard + +To access the Arcade Cloud dashboard, go to [api.arcade.dev/dashboard](https://api.arcade.dev/dashboard). If you are self-hosting, by default the dashboard will be available at http://localhost:9099/dashboard. Adjust the host and port number to match your environment. + +#### Navigate to the OAuth Providers page + +- Under the **OAuth** section of the Arcade Dashboard left-side menu, click **Providers**. +- Click **Add OAuth Provider** in the top right corner. +- Select the **Included Providers** tab at the top. +- In the **Provider** dropdown, select **Calendly**. + +#### Enter the provider details + +- Choose a unique **ID** for your provider (e.g. "my-calendly-provider"). +- Optionally enter a **Description**. +- Enter the **Client ID** and **Client Secret** from your Calendly app. +- Note the **Redirect URL** generated by Arcade. This must be added to your Calendly app's Redirect URIs. + +#### Create the provider + +Hit the **Create** button and the provider will be ready to be used. + + + +When you use tools that require Calendly auth using your Arcade account credentials, Arcade will automatically use this Calendly OAuth provider. If you have multiple Calendly providers, see [using multiple auth providers of the same type](/home/auth-providers#using-multiple-providers-of-the-same-type) for more information. + + + + +## Using Calendly auth in app code + +Use the Calendly auth provider in your own agents and AI apps to get a user-scoped token for the Calendly API. See [authorizing agents with Arcade](/home/auth/how-arcade-helps) to understand how this works. + +Use `client.auth.start()` to get a user token for the Calendly API: + + + + +```python {21-22} +from arcadepy import Arcade + +client = Arcade(base_url="https://api.arcade.dev") # Automatically finds the `ARCADE_API_KEY` env variable + +user_id = "{arcade_user_id}" + +# Start the authorization process +auth_response = client.auth.start( + user_id=user_id, + provider="calendly", + scopes=["default"], +) + +if auth_response.status != "completed": + print("Please complete the authorization challenge in your browser:") + print(auth_response.url) + +# Wait for the authorization to complete +auth_response = client.auth.wait_for_completion(auth_response) + +# Do something interesting with the token... +auth_token = auth_response.context.token +``` + + + + + +```javascript {20-21} +import { Arcade } from "@arcadeai/arcadejs"; + +const client = new Arcade({ baseURL: "https://api.arcade.dev" }); // Automatically finds the `ARCADE_API_KEY` env variable + +const userId = "{arcade_user_id}"; + +// Start the authorization process +const authResponse = await client.auth.start(userId, "calendly", { + scopes: ["default"], +}); + +if (authResponse.status !== "completed") { + console.log("Please complete the authorization challenge in your browser:"); + console.log(authResponse.url); +} + +// Wait for the authorization to complete +const response = await client.auth.waitForCompletion(authResponse); + +// Do something interesting with the token... +const auth_token = response.context.token; +``` + + + + +You can use the auth token to call the [Calendly API](https://developer.calendly.com/api-docs) endpoints to manage events, scheduling links, and user information. + +## Using Calendly auth in custom tools + +You can author your own [custom tools](/home/build-tools/create-a-mcp-server) that interact with Calendly API. + +Use the `OAuth2()` auth class to specify that a tool requires authorization with Calendly. The authentication token needed to call the Calendly API is available in the tool context through the `context.authorization.token` property. + +```python {9,17} +from typing import Annotated + +import httpx + +from arcade_tdk import ToolContext, tool +from arcade_tdk.auth import OAuth2 + + +@tool(requires_auth=OAuth2(provider_id="calendly", scopes=["default"])) +async def get_user_events( + context: ToolContext, + user_uri: Annotated[str, "The URI of the user whose events to retrieve."], +) -> Annotated[dict, "User events information"]: + """Retrieves scheduled events for a Calendly user.""" + url = "https://api.calendly.com/scheduled_events" + headers = { + "Authorization": f"Bearer {context.authorization.token}", + "Accept": "application/json", + } + params = {"user": user_uri} + + async with httpx.AsyncClient() as client: + response = await client.get(url, headers=headers, params=params) + response.raise_for_status() + return response.json() +``` + +Your new tool can be called like demonstrated below: + + + + + If you are self-hosting, change the `base_url` parameter in the `Arcade` constructor to match your Arcade Engine URL. By default, the Engine will be available at `http://localhost:9099`. + + +```python +from arcadepy import Arcade + +client = Arcade(base_url="https://api.arcade.dev") # Automatically finds the `ARCADE_API_KEY` env variable + +USER_ID = "{arcade_user_id}" +TOOL_NAME = "Calendly.GetUserEvents" + +auth_response = client.tools.authorize(tool_name=TOOL_NAME, user_id=USER_ID) + +if auth_response.status != "completed": + print(f"Click this link to authorize: {auth_response.url}") + +# Wait for the authorization to complete +client.auth.wait_for_completion(auth_response) + +tool_input = { + "user_uri": "https://api.calendly.com/users/AAAAAAAAAAAAAAAA", +} + +response = client.tools.execute( + tool_name=TOOL_NAME, + input=tool_input, + user_id=USER_ID, +) +print(response.output.value) +``` + + + + + If you are self-hosting, change the `baseURL` parameter in the `Arcade` constructor to match your Arcade Engine URL. By default, the Engine will be available at `http://localhost:9099`. + + +```javascript +import { Arcade } from "@arcadeai/arcadejs"; + +const client = new Arcade({ baseURL: "https://api.arcade.dev" }); // Automatically finds the `ARCADE_API_KEY` env variable + +const USER_ID = "{arcade_user_id}"; +const TOOL_NAME = "Calendly.GetUserEvents"; + +// Start the authorization process +const authResponse = await client.tools.authorize({ + tool_name: TOOL_NAME, + user_id: USER_ID, +}); + +if (authResponse.status !== "completed") { + console.log(`Click this link to authorize: ${authResponse.url}`); +} + +// Wait for the authorization to complete +await client.auth.waitForCompletion(authResponse); + +const toolInput = { + user_uri: "https://api.calendly.com/users/AAAAAAAAAAAAAAAA", +}; + +const response = await client.tools.execute({ + tool_name: TOOL_NAME, + input: toolInput, + user_id: USER_ID, +}); + +console.log(response.output.value); +``` + + + diff --git a/app/en/home/auth-providers/miro/page.mdx b/app/en/home/auth-providers/miro/page.mdx new file mode 100644 index 000000000..ee67e149f --- /dev/null +++ b/app/en/home/auth-providers/miro/page.mdx @@ -0,0 +1,268 @@ +import { Tabs, Callout, Steps } from "nextra/components"; + +# Miro + +The Miro auth provider enables tools and agents to call Miro APIs on behalf of a user. + +## What's documented here + +This page describes how to use and configure Miro auth with Arcade. + +This auth provider is used by: + +- Your [app code](#using-miro-auth-in-app-code) that needs to call Miro APIs +- Or, your [custom tools](#using-miro-auth-in-custom-tools) that need to call Miro APIs + +## Use Arcade's Default Miro Auth Provider + +Arcade offers a default Miro auth provider that you can use in the Arcade Cloud Platform. In this case, your users will see `Arcade` as the name of the application that's requesting permission. + +If you choose to use Arcade's Miro auth, you don't need to configure anything. + +## Use Your Own Miro App Credentials + + + When using your own app credentials, make sure you configure your project to + use a [custom user + verifier](/home/auth/secure-auth-production#build-a-custom-user-verifier). + Without this, your end-users will not be able to use your app or agent in + production. + + +In a production environment, you will most likely want to use your own Miro app credentials. This way, your users will see your application's name requesting permission. + +Before showing how to configure your Miro app credentials, let's go through the steps to create a Miro app. + +## Create a Miro App + +Follow the documentation on [Building Apps for Miro](https://developers.miro.com/docs/build-your-first-hello-world-app). You will need to create a developer team to build apps. + +When creating your app, use the following settings: + +- Set an appropriate App name and description. This will be visible to your users authorizing access to your app. +- In the **App Credentials** section: + - Take note of the **Client ID** and **Client Secret**. +- In the **Redirect URI for OAuth2.0** section: + - Add the redirect URL generated by Arcade (see below). +- In the **Permissions** section: + - Select the appropriate permissions/scopes for your app. Common scopes include: + - `boards:read` - Read access to boards + - `boards:write` - Write access to boards +- Install the app to your team to test it. + +## Configuring your own Miro Auth Provider in Arcade + + + + +### Configure Miro Auth Using the Arcade Dashboard GUI + + + +#### Access the Arcade Dashboard + +To access the Arcade Cloud dashboard, go to [api.arcade.dev/dashboard](https://api.arcade.dev/dashboard). If you are self-hosting, by default the dashboard will be available at http://localhost:9099/dashboard. Adjust the host and port number to match your environment. + +#### Navigate to the OAuth Providers page + +- Under the **OAuth** section of the Arcade Dashboard left-side menu, click **Providers**. +- Click **Add OAuth Provider** in the top right corner. +- Select the **Included Providers** tab at the top. +- In the **Provider** dropdown, select **Miro**. + +#### Enter the provider details + +- Choose a unique **ID** for your provider (e.g. "my-miro-provider"). +- Optionally enter a **Description**. +- Enter the **Client ID** and **Client Secret** from your Miro app. +- Note the **Redirect URL** generated by Arcade. This must be added to your Miro app's Redirect URIs. + +#### Create the provider + +Hit the **Create** button and the provider will be ready to be used. + + + +When you use tools that require Miro auth using your Arcade account credentials, Arcade will automatically use this Miro OAuth provider. If you have multiple Miro providers, see [using multiple auth providers of the same type](/home/auth-providers#using-multiple-providers-of-the-same-type) for more information. + + + + +## Using Miro auth in app code + +Use the Miro auth provider in your own agents and AI apps to get a user-scoped token for the Miro API. See [authorizing agents with Arcade](/home/auth/how-arcade-helps) to understand how this works. + +Use `client.auth.start()` to get a user token for the Miro API: + + + + +```python {21-22} +from arcadepy import Arcade + +client = Arcade(base_url="https://api.arcade.dev") # Automatically finds the `ARCADE_API_KEY` env variable + +user_id = "{arcade_user_id}" + +# Start the authorization process +auth_response = client.auth.start( + user_id=user_id, + provider="miro", + scopes=["boards:read", "boards:write"], +) + +if auth_response.status != "completed": + print("Please complete the authorization challenge in your browser:") + print(auth_response.url) + +# Wait for the authorization to complete +auth_response = client.auth.wait_for_completion(auth_response) + +# Do something interesting with the token... +auth_token = auth_response.context.token +``` + + + + + +```javascript {20-21} +import { Arcade } from "@arcadeai/arcadejs"; + +const client = new Arcade({ baseURL: "https://api.arcade.dev" }); // Automatically finds the `ARCADE_API_KEY` env variable + +const userId = "{arcade_user_id}"; + +// Start the authorization process +const authResponse = await client.auth.start(userId, "miro", { + scopes: ["boards:read", "boards:write"], +}); + +if (authResponse.status !== "completed") { + console.log("Please complete the authorization challenge in your browser:"); + console.log(authResponse.url); +} + +// Wait for the authorization to complete +const response = await client.auth.waitForCompletion(authResponse); + +// Do something interesting with the token... +const auth_token = response.context.token; +``` + + + + +You can use the auth token to call the [Miro REST API](https://developers.miro.com/reference/api-reference) endpoints to interact with boards, widgets, and other Miro resources. + +## Using Miro auth in custom tools + +You can author your own [custom tools](/home/build-tools/create-a-mcp-server) that interact with Miro API. + +Use the `OAuth2()` auth class to specify that a tool requires authorization with Miro. The authentication token needed to call the Miro API is available in the tool context through the `context.authorization.token` property. + +```python {9,17} +from typing import Annotated + +import httpx + +from arcade_tdk import ToolContext, tool +from arcade_tdk.auth import OAuth2 + + +@tool(requires_auth=OAuth2(provider_id="miro", scopes=["boards:read"])) +async def get_board( + context: ToolContext, + board_id: Annotated[str, "The ID of the board to retrieve."], +) -> Annotated[dict, "Board information"]: + """Retrieves information about a Miro board.""" + url = f"https://api.miro.com/v2/boards/{board_id}" + headers = { + "Authorization": f"Bearer {context.authorization.token}", + "Accept": "application/json", + } + + async with httpx.AsyncClient() as client: + response = await client.get(url, headers=headers) + response.raise_for_status() + return response.json() +``` + +Your new tool can be called like demonstrated below: + + + + + If you are self-hosting, change the `base_url` parameter in the `Arcade` constructor to match your Arcade Engine URL. By default, the Engine will be available at `http://localhost:9099`. + + +```python +from arcadepy import Arcade + +client = Arcade(base_url="https://api.arcade.dev") # Automatically finds the `ARCADE_API_KEY` env variable + +USER_ID = "{arcade_user_id}" +TOOL_NAME = "Miro.GetBoard" + +auth_response = client.tools.authorize(tool_name=TOOL_NAME, user_id=USER_ID) + +if auth_response.status != "completed": + print(f"Click this link to authorize: {auth_response.url}") + +# Wait for the authorization to complete +client.auth.wait_for_completion(auth_response) + +tool_input = { + "board_id": "uXjVK1234567", +} + +response = client.tools.execute( + tool_name=TOOL_NAME, + input=tool_input, + user_id=USER_ID, +) +print(response.output.value) +``` + + + + + If you are self-hosting, change the `baseURL` parameter in the `Arcade` constructor to match your Arcade Engine URL. By default, the Engine will be available at `http://localhost:9099`. + + +```javascript +import { Arcade } from "@arcadeai/arcadejs"; + +const client = new Arcade({ baseURL: "https://api.arcade.dev" }); // Automatically finds the `ARCADE_API_KEY` env variable + +const USER_ID = "{arcade_user_id}"; +const TOOL_NAME = "Miro.GetBoard"; + +// Start the authorization process +const authResponse = await client.tools.authorize({ + tool_name: TOOL_NAME, + user_id: USER_ID, +}); + +if (authResponse.status !== "completed") { + console.log(`Click this link to authorize: ${authResponse.url}`); +} + +// Wait for the authorization to complete +await client.auth.waitForCompletion(authResponse); + +const toolInput = { + board_id: "uXjVK1234567", +}; + +const response = await client.tools.execute({ + tool_name: TOOL_NAME, + input: toolInput, + user_id: USER_ID, +}); + +console.log(response.output.value); +``` + + + diff --git a/app/en/home/auth-providers/pagerduty/page.mdx b/app/en/home/auth-providers/pagerduty/page.mdx new file mode 100644 index 000000000..44f91b387 --- /dev/null +++ b/app/en/home/auth-providers/pagerduty/page.mdx @@ -0,0 +1,266 @@ +import { Tabs, Callout, Steps } from "nextra/components"; + +# PagerDuty + +The PagerDuty auth provider enables tools and agents to call PagerDuty APIs on behalf of a user. + +## What's documented here + +This page describes how to use and configure PagerDuty auth with Arcade. + +This auth provider is used by: + +- Your [app code](#using-pagerduty-auth-in-app-code) that needs to call PagerDuty APIs +- Or, your [custom tools](#using-pagerduty-auth-in-custom-tools) that need to call PagerDuty APIs + +## Use Arcade's Default PagerDuty Auth Provider + +Arcade offers a default PagerDuty auth provider that you can use in the Arcade Cloud Platform. In this case, your users will see `Arcade` as the name of the application that's requesting permission. + +If you choose to use Arcade's PagerDuty auth, you don't need to configure anything. + +## Use Your Own PagerDuty App Credentials + + + When using your own app credentials, make sure you configure your project to + use a [custom user + verifier](/home/auth/secure-auth-production#build-a-custom-user-verifier). + Without this, your end-users will not be able to use your app or agent in + production. + + +In a production environment, you will most likely want to use your own PagerDuty app credentials. This way, your users will see your application's name requesting permission. + +Before showing how to configure your PagerDuty app credentials, let's go through the steps to create a PagerDuty app. + +## Create a PagerDuty App + +Follow the documentation on [PagerDuty API Documentation](https://developer.pagerduty.com/docs/). You will need to create an app in your PagerDuty account. + +When creating your app, use the following settings: + +- Set an appropriate App name and description. This will be visible to your users authorizing access to your app. +- In the **App Registration** section: + - Take note of the **Client ID** and **Client Secret**. + - Add the redirect URL generated by Arcade (see below) to the **Redirect URLs**. +- Configure the appropriate **Scopes** for your application. Common scopes include: + - `read` - Read access to PagerDuty resources + - `write` - Write access to PagerDuty resources + +## Configuring your own PagerDuty Auth Provider in Arcade + + + + +### Configure PagerDuty Auth Using the Arcade Dashboard GUI + + + +#### Access the Arcade Dashboard + +To access the Arcade Cloud dashboard, go to [api.arcade.dev/dashboard](https://api.arcade.dev/dashboard). If you are self-hosting, by default the dashboard will be available at http://localhost:9099/dashboard. Adjust the host and port number to match your environment. + +#### Navigate to the OAuth Providers page + +- Under the **OAuth** section of the Arcade Dashboard left-side menu, click **Providers**. +- Click **Add OAuth Provider** in the top right corner. +- Select the **Included Providers** tab at the top. +- In the **Provider** dropdown, select **PagerDuty**. + +#### Enter the provider details + +- Choose a unique **ID** for your provider (e.g. "my-pagerduty-provider"). +- Optionally enter a **Description**. +- Enter the **Client ID** and **Client Secret** from your PagerDuty app. +- Note the **Redirect URL** generated by Arcade. This must be added to your PagerDuty app's Redirect URLs. + +#### Create the provider + +Hit the **Create** button and the provider will be ready to be used. + + + +When you use tools that require PagerDuty auth using your Arcade account credentials, Arcade will automatically use this PagerDuty OAuth provider. If you have multiple PagerDuty providers, see [using multiple auth providers of the same type](/home/auth-providers#using-multiple-providers-of-the-same-type) for more information. + + + + +## Using PagerDuty auth in app code + +Use the PagerDuty auth provider in your own agents and AI apps to get a user-scoped token for the PagerDuty API. See [authorizing agents with Arcade](/home/auth/how-arcade-helps) to understand how this works. + +Use `client.auth.start()` to get a user token for the PagerDuty API: + + + + +```python {21-22} +from arcadepy import Arcade + +client = Arcade(base_url="https://api.arcade.dev") # Automatically finds the `ARCADE_API_KEY` env variable + +user_id = "{arcade_user_id}" + +# Start the authorization process +auth_response = client.auth.start( + user_id=user_id, + provider="pagerduty", + scopes=["read", "write"], +) + +if auth_response.status != "completed": + print("Please complete the authorization challenge in your browser:") + print(auth_response.url) + +# Wait for the authorization to complete +auth_response = client.auth.wait_for_completion(auth_response) + +# Do something interesting with the token... +auth_token = auth_response.context.token +``` + + + + + +```javascript {20-21} +import { Arcade } from "@arcadeai/arcadejs"; + +const client = new Arcade({ baseURL: "https://api.arcade.dev" }); // Automatically finds the `ARCADE_API_KEY` env variable + +const userId = "{arcade_user_id}"; + +// Start the authorization process +const authResponse = await client.auth.start(userId, "pagerduty", { + scopes: ["read", "write"], +}); + +if (authResponse.status !== "completed") { + console.log("Please complete the authorization challenge in your browser:"); + console.log(authResponse.url); +} + +// Wait for the authorization to complete +const response = await client.auth.waitForCompletion(authResponse); + +// Do something interesting with the token... +const auth_token = response.context.token; +``` + + + + +You can use the auth token to call the [PagerDuty REST API](https://developer.pagerduty.com/api-reference/) endpoints to manage incidents, services, schedules, and more. + +## Using PagerDuty auth in custom tools + +You can author your own [custom tools](/home/build-tools/create-a-mcp-server) that interact with PagerDuty API. + +Use the `OAuth2()` auth class to specify that a tool requires authorization with PagerDuty. The authentication token needed to call the PagerDuty API is available in the tool context through the `context.authorization.token` property. + +```python {9,17} +from typing import Annotated + +import httpx + +from arcade_tdk import ToolContext, tool +from arcade_tdk.auth import OAuth2 + + +@tool(requires_auth=OAuth2(provider_id="pagerduty", scopes=["read"])) +async def get_incidents( + context: ToolContext, + status: Annotated[str, "Filter by incident status (triggered, acknowledged, resolved)."] = "triggered", +) -> Annotated[dict, "List of incidents"]: + """Retrieves PagerDuty incidents.""" + url = "https://api.pagerduty.com/incidents" + headers = { + "Authorization": f"Bearer {context.authorization.token}", + "Accept": "application/vnd.pagerduty+json;version=2", + } + params = {"statuses[]": status} + + async with httpx.AsyncClient() as client: + response = await client.get(url, headers=headers, params=params) + response.raise_for_status() + return response.json() +``` + +Your new tool can be called like demonstrated below: + + + + + If you are self-hosting, change the `base_url` parameter in the `Arcade` constructor to match your Arcade Engine URL. By default, the Engine will be available at `http://localhost:9099`. + + +```python +from arcadepy import Arcade + +client = Arcade(base_url="https://api.arcade.dev") # Automatically finds the `ARCADE_API_KEY` env variable + +USER_ID = "{arcade_user_id}" +TOOL_NAME = "PagerDuty.GetIncidents" + +auth_response = client.tools.authorize(tool_name=TOOL_NAME, user_id=USER_ID) + +if auth_response.status != "completed": + print(f"Click this link to authorize: {auth_response.url}") + +# Wait for the authorization to complete +client.auth.wait_for_completion(auth_response) + +tool_input = { + "status": "triggered", +} + +response = client.tools.execute( + tool_name=TOOL_NAME, + input=tool_input, + user_id=USER_ID, +) +print(response.output.value) +``` + + + + + If you are self-hosting, change the `baseURL` parameter in the `Arcade` constructor to match your Arcade Engine URL. By default, the Engine will be available at `http://localhost:9099`. + + +```javascript +import { Arcade } from "@arcadeai/arcadejs"; + +const client = new Arcade({ baseURL: "https://api.arcade.dev" }); // Automatically finds the `ARCADE_API_KEY` env variable + +const USER_ID = "{arcade_user_id}"; +const TOOL_NAME = "PagerDuty.GetIncidents"; + +// Start the authorization process +const authResponse = await client.tools.authorize({ + tool_name: TOOL_NAME, + user_id: USER_ID, +}); + +if (authResponse.status !== "completed") { + console.log(`Click this link to authorize: ${authResponse.url}`); +} + +// Wait for the authorization to complete +await client.auth.waitForCompletion(authResponse); + +const toolInput = { + status: "triggered", +}; + +const response = await client.tools.execute({ + tool_name: TOOL_NAME, + input: toolInput, + user_id: USER_ID, +}); + +console.log(response.output.value); +``` + + + diff --git a/app/en/home/auth-providers/squareup/page.mdx b/app/en/home/auth-providers/squareup/page.mdx new file mode 100644 index 000000000..60f510715 --- /dev/null +++ b/app/en/home/auth-providers/squareup/page.mdx @@ -0,0 +1,271 @@ +import { Tabs, Callout, Steps } from "nextra/components"; + +# Square + +The Square auth provider enables tools and agents to call Square APIs on behalf of a user. + +## What's documented here + +This page describes how to use and configure Square auth with Arcade. + +This auth provider is used by: + +- Your [app code](#using-square-auth-in-app-code) that needs to call Square APIs +- Or, your [custom tools](#using-square-auth-in-custom-tools) that need to call Square APIs + +## Use Arcade's Default Square Auth Provider + +Arcade offers a default Square auth provider that you can use in the Arcade Cloud Platform. In this case, your users will see `Arcade` as the name of the application that's requesting permission. + +If you choose to use Arcade's Square auth, you don't need to configure anything. + +## Use Your Own Square App Credentials + + + When using your own app credentials, make sure you configure your project to + use a [custom user + verifier](/home/auth/secure-auth-production#build-a-custom-user-verifier). + Without this, your end-users will not be able to use your app or agent in + production. + + +In a production environment, you will most likely want to use your own Square app credentials. This way, your users will see your application's name requesting permission. + +Before showing how to configure your Square app credentials, let's go through the steps to create a Square app. + +## Create a Square App + +Follow the documentation on [Square Developer Platform](https://developer.squareup.com/docs). You will need to create a Square developer account. + +When creating your app, use the following settings: + +- Set an appropriate App name and description. This will be visible to your users authorizing access to your app. +- In the **OAuth** section: + - Take note of the **Application ID** (Client ID) and **Application Secret** (Client Secret). + - Add the redirect URL generated by Arcade (see below) to the **Redirect URL** field. +- Configure the appropriate **Permissions** for your application. Common permissions include: + - `MERCHANT_PROFILE_READ` - Read merchant profile information + - `PAYMENTS_READ` - Read payment information + - `ORDERS_READ` - Read order information + - `ORDERS_WRITE` - Create and update orders + - `ITEMS_READ` - Read catalog items + - `ITEMS_WRITE` - Create and update catalog items + +## Configuring your own Square Auth Provider in Arcade + + + + +### Configure Square Auth Using the Arcade Dashboard GUI + + + +#### Access the Arcade Dashboard + +To access the Arcade Cloud dashboard, go to [api.arcade.dev/dashboard](https://api.arcade.dev/dashboard). If you are self-hosting, by default the dashboard will be available at http://localhost:9099/dashboard. Adjust the host and port number to match your environment. + +#### Navigate to the OAuth Providers page + +- Under the **OAuth** section of the Arcade Dashboard left-side menu, click **Providers**. +- Click **Add OAuth Provider** in the top right corner. +- Select the **Included Providers** tab at the top. +- In the **Provider** dropdown, select **Square**. + +#### Enter the provider details + +- Choose a unique **ID** for your provider (e.g. "my-square-provider"). +- Optionally enter a **Description**. +- Enter the **Client ID** (Application ID) and **Client Secret** (Application Secret) from your Square app. +- Note the **Redirect URL** generated by Arcade. This must be added to your Square app's Redirect URL. + +#### Create the provider + +Hit the **Create** button and the provider will be ready to be used. + + + +When you use tools that require Square auth using your Arcade account credentials, Arcade will automatically use this Square OAuth provider. If you have multiple Square providers, see [using multiple auth providers of the same type](/home/auth-providers#using-multiple-providers-of-the-same-type) for more information. + + + + +## Using Square auth in app code + +Use the Square auth provider in your own agents and AI apps to get a user-scoped token for the Square API. See [authorizing agents with Arcade](/home/auth/how-arcade-helps) to understand how this works. + +Use `client.auth.start()` to get a user token for the Square API: + + + + +```python {21-22} +from arcadepy import Arcade + +client = Arcade(base_url="https://api.arcade.dev") # Automatically finds the `ARCADE_API_KEY` env variable + +user_id = "{arcade_user_id}" + +# Start the authorization process +auth_response = client.auth.start( + user_id=user_id, + provider="squareup", + scopes=["MERCHANT_PROFILE_READ", "PAYMENTS_READ"], +) + +if auth_response.status != "completed": + print("Please complete the authorization challenge in your browser:") + print(auth_response.url) + +# Wait for the authorization to complete +auth_response = client.auth.wait_for_completion(auth_response) + +# Do something interesting with the token... +auth_token = auth_response.context.token +``` + + + + + +```javascript {20-21} +import { Arcade } from "@arcadeai/arcadejs"; + +const client = new Arcade({ baseURL: "https://api.arcade.dev" }); // Automatically finds the `ARCADE_API_KEY` env variable + +const userId = "{arcade_user_id}"; + +// Start the authorization process +const authResponse = await client.auth.start(userId, "squareup", { + scopes: ["MERCHANT_PROFILE_READ", "PAYMENTS_READ"], +}); + +if (authResponse.status !== "completed") { + console.log("Please complete the authorization challenge in your browser:"); + console.log(authResponse.url); +} + +// Wait for the authorization to complete +const response = await client.auth.waitForCompletion(authResponse); + +// Do something interesting with the token... +const auth_token = response.context.token; +``` + + + + +You can use the auth token to call the [Square API](https://developer.squareup.com/reference/square) endpoints to manage payments, orders, catalog items, and more. + +## Using Square auth in custom tools + +You can author your own [custom tools](/home/build-tools/create-a-mcp-server) that interact with Square API. + +Use the `OAuth2()` auth class to specify that a tool requires authorization with Square. The authentication token needed to call the Square API is available in the tool context through the `context.authorization.token` property. + +```python {9,17} +from typing import Annotated + +import httpx + +from arcade_tdk import ToolContext, tool +from arcade_tdk.auth import OAuth2 + + +@tool(requires_auth=OAuth2(provider_id="squareup", scopes=["PAYMENTS_READ"])) +async def list_payments( + context: ToolContext, + location_id: Annotated[str, "The ID of the location to list payments for."], +) -> Annotated[dict, "List of payments"]: + """Retrieves a list of payments for a Square location.""" + url = "https://connect.squareup.com/v2/payments" + headers = { + "Authorization": f"Bearer {context.authorization.token}", + "Accept": "application/json", + "Square-Version": "2024-01-18", + } + params = {"location_id": location_id} + + async with httpx.AsyncClient() as client: + response = await client.get(url, headers=headers, params=params) + response.raise_for_status() + return response.json() +``` + +Your new tool can be called like demonstrated below: + + + + + If you are self-hosting, change the `base_url` parameter in the `Arcade` constructor to match your Arcade Engine URL. By default, the Engine will be available at `http://localhost:9099`. + + +```python +from arcadepy import Arcade + +client = Arcade(base_url="https://api.arcade.dev") # Automatically finds the `ARCADE_API_KEY` env variable + +USER_ID = "{arcade_user_id}" +TOOL_NAME = "SquareUp.ListPayments" + +auth_response = client.tools.authorize(tool_name=TOOL_NAME, user_id=USER_ID) + +if auth_response.status != "completed": + print(f"Click this link to authorize: {auth_response.url}") + +# Wait for the authorization to complete +client.auth.wait_for_completion(auth_response) + +tool_input = { + "location_id": "LOCATION123", +} + +response = client.tools.execute( + tool_name=TOOL_NAME, + input=tool_input, + user_id=USER_ID, +) +print(response.output.value) +``` + + + + + If you are self-hosting, change the `baseURL` parameter in the `Arcade` constructor to match your Arcade Engine URL. By default, the Engine will be available at `http://localhost:9099`. + + +```javascript +import { Arcade } from "@arcadeai/arcadejs"; + +const client = new Arcade({ baseURL: "https://api.arcade.dev" }); // Automatically finds the `ARCADE_API_KEY` env variable + +const USER_ID = "{arcade_user_id}"; +const TOOL_NAME = "SquareUp.ListPayments"; + +// Start the authorization process +const authResponse = await client.tools.authorize({ + tool_name: TOOL_NAME, + user_id: USER_ID, +}); + +if (authResponse.status !== "completed") { + console.log(`Click this link to authorize: ${authResponse.url}`); +} + +// Wait for the authorization to complete +await client.auth.waitForCompletion(authResponse); + +const toolInput = { + location_id: "LOCATION123", +}; + +const response = await client.tools.execute({ + tool_name: TOOL_NAME, + input: toolInput, + user_id: USER_ID, +}); + +console.log(response.output.value); +``` + + + diff --git a/examples/code/integrations/airtable/config_provider.engine.yaml b/examples/code/integrations/airtable/config_provider.engine.yaml new file mode 100644 index 000000000..88f39021f --- /dev/null +++ b/examples/code/integrations/airtable/config_provider.engine.yaml @@ -0,0 +1,9 @@ +auth: + providers: + - id: arcade-airtable + description: "Arcade's default Airtable provider" + enabled: true + type: oauth2 + provider_id: airtable + client_id: ${env:AIRTABLE_CLIENT_ID} + client_secret: ${env:AIRTABLE_CLIENT_SECRET} diff --git a/examples/code/integrations/airtable/custom_auth.js b/examples/code/integrations/airtable/custom_auth.js new file mode 100644 index 000000000..96e8d027a --- /dev/null +++ b/examples/code/integrations/airtable/custom_auth.js @@ -0,0 +1,22 @@ +import { Arcade } from "@arcadeai/arcadejs"; + +const client = new Arcade(); // Automatically finds the `ARCADE_API_KEY` env variable + +const userId = "{arcade_user_id}"; + +// Start the authorization process +let authResponse = await client.auth.start(userId, "arcade-airtable", { + scopes: ["data.records:read", "data.records:write", "schema.bases:read"], +}); + +if (authResponse.status !== "completed") { + console.log("Please complete the authorization challenge in your browser:"); + console.log(authResponse.url); +} + +// Wait for the authorization to complete +authResponse = await client.auth.waitForCompletion(authResponse); + +const token = authResponse.context.token; +// TODO: Do something interesting with the token... + diff --git a/examples/code/integrations/airtable/custom_auth.py b/examples/code/integrations/airtable/custom_auth.py new file mode 100644 index 000000000..bf350a114 --- /dev/null +++ b/examples/code/integrations/airtable/custom_auth.py @@ -0,0 +1,26 @@ +from arcadepy import Arcade + +client = Arcade() # Automatically finds the `ARCADE_API_KEY` env variable + +user_id = "{arcade_user_id}" + +# Start the authorization process +auth_response = client.auth.start( + user_id=user_id, + provider="arcade-airtable", + scopes=["data.records:read", "data.records:write", "schema.bases:read"], +) + +if auth_response.status != "completed": + print("Please complete the authorization challenge in your browser:") + print(auth_response.url) + +# Wait for the authorization to complete +auth_response = client.auth.wait_for_completion(auth_response) + +if not auth_response.context.token: + raise ValueError("No token found in auth response") + +token = auth_response.context.token +# TODO: Do something interesting with the token... + diff --git a/examples/code/integrations/airtable/custom_tool.py b/examples/code/integrations/airtable/custom_tool.py new file mode 100644 index 000000000..f51b2f675 --- /dev/null +++ b/examples/code/integrations/airtable/custom_tool.py @@ -0,0 +1,27 @@ +from typing import Annotated + +import httpx + +from arcade_tdk import ToolContext, tool +from arcade_tdk.auth import OAuth2 + + +@tool(requires_auth=OAuth2(id="arcade-airtable", scopes=["data.records:read", "data.records:write", "schema.bases:read"])) +async def get_airtable_bases( + context: ToolContext, +) -> Annotated[dict, "List of Airtable bases"]: + """Get all bases the authenticated user has access to.""" + if not context.authorization or not context.authorization.token: + raise ValueError("No token found in context") + + url = "https://api.airtable.com/v0/meta/bases" + headers = { + "Authorization": f"Bearer {context.authorization.token}", + "Content-Type": "application/json", + } + + async with httpx.AsyncClient() as client: + response = await client.get(url, headers=headers) + response.raise_for_status() + return response.json() + diff --git a/examples/code/integrations/calendly/config_provider.engine.yaml b/examples/code/integrations/calendly/config_provider.engine.yaml new file mode 100644 index 000000000..0cf688554 --- /dev/null +++ b/examples/code/integrations/calendly/config_provider.engine.yaml @@ -0,0 +1,9 @@ +auth: + providers: + - id: arcade-calendly + description: "Arcade's default Calendly provider" + enabled: true + type: oauth2 + provider_id: calendly + client_id: ${env:CALENDLY_CLIENT_ID} + client_secret: ${env:CALENDLY_CLIENT_SECRET} diff --git a/examples/code/integrations/calendly/custom_auth.js b/examples/code/integrations/calendly/custom_auth.js new file mode 100644 index 000000000..c613268c5 --- /dev/null +++ b/examples/code/integrations/calendly/custom_auth.js @@ -0,0 +1,22 @@ +import { Arcade } from "@arcadeai/arcadejs"; + +const client = new Arcade(); // Automatically finds the `ARCADE_API_KEY` env variable + +const userId = "{arcade_user_id}"; + +// Start the authorization process +let authResponse = await client.auth.start(userId, "arcade-calendly", { + scopes: ["default"], +}); + +if (authResponse.status !== "completed") { + console.log("Please complete the authorization challenge in your browser:"); + console.log(authResponse.url); +} + +// Wait for the authorization to complete +authResponse = await client.auth.waitForCompletion(authResponse); + +const token = authResponse.context.token; +// TODO: Do something interesting with the token... + diff --git a/examples/code/integrations/calendly/custom_auth.py b/examples/code/integrations/calendly/custom_auth.py new file mode 100644 index 000000000..0c2f7681c --- /dev/null +++ b/examples/code/integrations/calendly/custom_auth.py @@ -0,0 +1,26 @@ +from arcadepy import Arcade + +client = Arcade() # Automatically finds the `ARCADE_API_KEY` env variable + +user_id = "{arcade_user_id}" + +# Start the authorization process +auth_response = client.auth.start( + user_id=user_id, + provider="arcade-calendly", + scopes=["default"], +) + +if auth_response.status != "completed": + print("Please complete the authorization challenge in your browser:") + print(auth_response.url) + +# Wait for the authorization to complete +auth_response = client.auth.wait_for_completion(auth_response) + +if not auth_response.context.token: + raise ValueError("No token found in auth response") + +token = auth_response.context.token +# TODO: Do something interesting with the token... + diff --git a/examples/code/integrations/calendly/custom_tool.py b/examples/code/integrations/calendly/custom_tool.py new file mode 100644 index 000000000..28ec9a06c --- /dev/null +++ b/examples/code/integrations/calendly/custom_tool.py @@ -0,0 +1,27 @@ +from typing import Annotated + +import httpx + +from arcade_tdk import ToolContext, tool +from arcade_tdk.auth import OAuth2 + + +@tool(requires_auth=OAuth2(id="arcade-calendly", scopes=["default"])) +async def get_calendly_user( + context: ToolContext, +) -> Annotated[dict, "Calendly user information"]: + """Get the authenticated user's Calendly profile information.""" + if not context.authorization or not context.authorization.token: + raise ValueError("No token found in context") + + url = "https://api.calendly.com/users/me" + headers = { + "Authorization": f"Bearer {context.authorization.token}", + "Content-Type": "application/json", + } + + async with httpx.AsyncClient() as client: + response = await client.get(url, headers=headers) + response.raise_for_status() + return response.json() + diff --git a/examples/code/integrations/miro/config_provider.engine.yaml b/examples/code/integrations/miro/config_provider.engine.yaml new file mode 100644 index 000000000..1a77a870e --- /dev/null +++ b/examples/code/integrations/miro/config_provider.engine.yaml @@ -0,0 +1,9 @@ +auth: + providers: + - id: arcade-miro + description: "Arcade's default Miro provider" + enabled: true + type: oauth2 + provider_id: miro + client_id: ${env:MIRO_CLIENT_ID} + client_secret: ${env:MIRO_CLIENT_SECRET} diff --git a/examples/code/integrations/miro/custom_auth.js b/examples/code/integrations/miro/custom_auth.js new file mode 100644 index 000000000..ac25ce729 --- /dev/null +++ b/examples/code/integrations/miro/custom_auth.js @@ -0,0 +1,22 @@ +import { Arcade } from "@arcadeai/arcadejs"; + +const client = new Arcade(); // Automatically finds the `ARCADE_API_KEY` env variable + +const userId = "{arcade_user_id}"; + +// Start the authorization process +let authResponse = await client.auth.start(userId, "arcade-miro", { + scopes: ["boards:read", "boards:write"], +}); + +if (authResponse.status !== "completed") { + console.log("Please complete the authorization challenge in your browser:"); + console.log(authResponse.url); +} + +// Wait for the authorization to complete +authResponse = await client.auth.waitForCompletion(authResponse); + +const token = authResponse.context.token; +// TODO: Do something interesting with the token... + diff --git a/examples/code/integrations/miro/custom_auth.py b/examples/code/integrations/miro/custom_auth.py new file mode 100644 index 000000000..70e441ea2 --- /dev/null +++ b/examples/code/integrations/miro/custom_auth.py @@ -0,0 +1,26 @@ +from arcadepy import Arcade + +client = Arcade() # Automatically finds the `ARCADE_API_KEY` env variable + +user_id = "{arcade_user_id}" + +# Start the authorization process +auth_response = client.auth.start( + user_id=user_id, + provider="arcade-miro", + scopes=["boards:read", "boards:write"], +) + +if auth_response.status != "completed": + print("Please complete the authorization challenge in your browser:") + print(auth_response.url) + +# Wait for the authorization to complete +auth_response = client.auth.wait_for_completion(auth_response) + +if not auth_response.context.token: + raise ValueError("No token found in auth response") + +token = auth_response.context.token +# TODO: Do something interesting with the token... + diff --git a/examples/code/integrations/miro/custom_tool.py b/examples/code/integrations/miro/custom_tool.py new file mode 100644 index 000000000..49789cbc1 --- /dev/null +++ b/examples/code/integrations/miro/custom_tool.py @@ -0,0 +1,27 @@ +from typing import Annotated + +import httpx + +from arcade_tdk import ToolContext, tool +from arcade_tdk.auth import OAuth2 + + +@tool(requires_auth=OAuth2(id="arcade-miro", scopes=["boards:read", "boards:write"])) +async def get_miro_boards( + context: ToolContext, +) -> Annotated[dict, "List of Miro boards"]: + """Get all boards the authenticated user has access to.""" + if not context.authorization or not context.authorization.token: + raise ValueError("No token found in context") + + url = "https://api.miro.com/v2/boards" + headers = { + "Authorization": f"Bearer {context.authorization.token}", + "Accept": "application/json", + } + + async with httpx.AsyncClient() as client: + response = await client.get(url, headers=headers) + response.raise_for_status() + return response.json() + diff --git a/examples/code/integrations/pagerduty/config_provider.engine.yaml b/examples/code/integrations/pagerduty/config_provider.engine.yaml new file mode 100644 index 000000000..6b10c5910 --- /dev/null +++ b/examples/code/integrations/pagerduty/config_provider.engine.yaml @@ -0,0 +1,9 @@ +auth: + providers: + - id: arcade-pagerduty + description: "Arcade's default PagerDuty provider" + enabled: true + type: oauth2 + provider_id: pagerduty + client_id: ${env:PAGERDUTY_CLIENT_ID} + client_secret: ${env:PAGERDUTY_CLIENT_SECRET} diff --git a/examples/code/integrations/pagerduty/custom_auth.js b/examples/code/integrations/pagerduty/custom_auth.js new file mode 100644 index 000000000..95b6049b0 --- /dev/null +++ b/examples/code/integrations/pagerduty/custom_auth.js @@ -0,0 +1,22 @@ +import { Arcade } from "@arcadeai/arcadejs"; + +const client = new Arcade(); // Automatically finds the `ARCADE_API_KEY` env variable + +const userId = "{arcade_user_id}"; + +// Start the authorization process +let authResponse = await client.auth.start(userId, "arcade-pagerduty", { + scopes: ["read", "write"], +}); + +if (authResponse.status !== "completed") { + console.log("Please complete the authorization challenge in your browser:"); + console.log(authResponse.url); +} + +// Wait for the authorization to complete +authResponse = await client.auth.waitForCompletion(authResponse); + +const token = authResponse.context.token; +// TODO: Do something interesting with the token... + diff --git a/examples/code/integrations/pagerduty/custom_auth.py b/examples/code/integrations/pagerduty/custom_auth.py new file mode 100644 index 000000000..f7618d46e --- /dev/null +++ b/examples/code/integrations/pagerduty/custom_auth.py @@ -0,0 +1,26 @@ +from arcadepy import Arcade + +client = Arcade() # Automatically finds the `ARCADE_API_KEY` env variable + +user_id = "{arcade_user_id}" + +# Start the authorization process +auth_response = client.auth.start( + user_id=user_id, + provider="arcade-pagerduty", + scopes=["read", "write"], +) + +if auth_response.status != "completed": + print("Please complete the authorization challenge in your browser:") + print(auth_response.url) + +# Wait for the authorization to complete +auth_response = client.auth.wait_for_completion(auth_response) + +if not auth_response.context.token: + raise ValueError("No token found in auth response") + +token = auth_response.context.token +# TODO: Do something interesting with the token... + diff --git a/examples/code/integrations/pagerduty/custom_tool.py b/examples/code/integrations/pagerduty/custom_tool.py new file mode 100644 index 000000000..512940c31 --- /dev/null +++ b/examples/code/integrations/pagerduty/custom_tool.py @@ -0,0 +1,28 @@ +from typing import Annotated + +import httpx + +from arcade_tdk import ToolContext, tool +from arcade_tdk.auth import OAuth2 + + +@tool(requires_auth=OAuth2(id="arcade-pagerduty", scopes=["read", "write"])) +async def get_pagerduty_incidents( + context: ToolContext, +) -> Annotated[dict, "List of PagerDuty incidents"]: + """Get all incidents from PagerDuty.""" + if not context.authorization or not context.authorization.token: + raise ValueError("No token found in context") + + url = "https://api.pagerduty.com/incidents" + headers = { + "Authorization": f"Bearer {context.authorization.token}", + "Accept": "application/vnd.pagerduty+json;version=2", + "Content-Type": "application/json", + } + + async with httpx.AsyncClient() as client: + response = await client.get(url, headers=headers) + response.raise_for_status() + return response.json() + diff --git a/examples/code/integrations/squareup/config_provider.engine.yaml b/examples/code/integrations/squareup/config_provider.engine.yaml new file mode 100644 index 000000000..8d74fdfb2 --- /dev/null +++ b/examples/code/integrations/squareup/config_provider.engine.yaml @@ -0,0 +1,9 @@ +auth: + providers: + - id: arcade-squareup + description: "Arcade's default Square provider" + enabled: true + type: oauth2 + provider_id: squareup + client_id: ${env:SQUARE_CLIENT_ID} + client_secret: ${env:SQUARE_CLIENT_SECRET} diff --git a/examples/code/integrations/squareup/custom_auth.js b/examples/code/integrations/squareup/custom_auth.js new file mode 100644 index 000000000..a101145d2 --- /dev/null +++ b/examples/code/integrations/squareup/custom_auth.js @@ -0,0 +1,22 @@ +import { Arcade } from "@arcadeai/arcadejs"; + +const client = new Arcade(); // Automatically finds the `ARCADE_API_KEY` env variable + +const userId = "{arcade_user_id}"; + +// Start the authorization process +let authResponse = await client.auth.start(userId, "arcade-squareup", { + scopes: ["MERCHANT_PROFILE_READ", "PAYMENTS_READ"], +}); + +if (authResponse.status !== "completed") { + console.log("Please complete the authorization challenge in your browser:"); + console.log(authResponse.url); +} + +// Wait for the authorization to complete +authResponse = await client.auth.waitForCompletion(authResponse); + +const token = authResponse.context.token; +// TODO: Do something interesting with the token... + diff --git a/examples/code/integrations/squareup/custom_auth.py b/examples/code/integrations/squareup/custom_auth.py new file mode 100644 index 000000000..4cb858f73 --- /dev/null +++ b/examples/code/integrations/squareup/custom_auth.py @@ -0,0 +1,26 @@ +from arcadepy import Arcade + +client = Arcade() # Automatically finds the `ARCADE_API_KEY` env variable + +user_id = "{arcade_user_id}" + +# Start the authorization process +auth_response = client.auth.start( + user_id=user_id, + provider="arcade-squareup", + scopes=["MERCHANT_PROFILE_READ", "PAYMENTS_READ"], +) + +if auth_response.status != "completed": + print("Please complete the authorization challenge in your browser:") + print(auth_response.url) + +# Wait for the authorization to complete +auth_response = client.auth.wait_for_completion(auth_response) + +if not auth_response.context.token: + raise ValueError("No token found in auth response") + +token = auth_response.context.token +# TODO: Do something interesting with the token... + diff --git a/examples/code/integrations/squareup/custom_tool.py b/examples/code/integrations/squareup/custom_tool.py new file mode 100644 index 000000000..23cc7c004 --- /dev/null +++ b/examples/code/integrations/squareup/custom_tool.py @@ -0,0 +1,28 @@ +from typing import Annotated + +import httpx + +from arcade_tdk import ToolContext, tool +from arcade_tdk.auth import OAuth2 + + +@tool(requires_auth=OAuth2(id="arcade-squareup", scopes=["MERCHANT_PROFILE_READ", "PAYMENTS_READ"])) +async def get_square_locations( + context: ToolContext, +) -> Annotated[dict, "List of Square locations"]: + """Get all business locations for the authenticated Square account.""" + if not context.authorization or not context.authorization.token: + raise ValueError("No token found in context") + + url = "https://connect.squareup.com/v2/locations" + headers = { + "Authorization": f"Bearer {context.authorization.token}", + "Content-Type": "application/json", + "Square-Version": "2024-10-17", + } + + async with httpx.AsyncClient() as client: + response = await client.get(url, headers=headers) + response.raise_for_status() + return response.json() +