diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000000..54a31c3b11e --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,2 @@ +/python @angrybayblade @tushar-composio +/js @himanshu-dixit @plxity diff --git a/.github/workflows/common.yml b/.github/workflows/common.yml index 04428b0b483..eab05728adf 100644 --- a/.github/workflows/common.yml +++ b/.github/workflows/common.yml @@ -17,9 +17,12 @@ jobs: os: [ubuntu-latest] python-version: ["3.10"] timeout-minutes: 10 + concurrency: + group: 'test:lock-check:${{ github.ref }}' + cancel-in-progress: true steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@master + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Pipenv install requirements and check it can be locked @@ -42,18 +45,17 @@ jobs: os: [ubuntu-latest] python-version: ["3.10"] timeout-minutes: 30 + concurrency: + group: 'test:linter_checks:${{ github.ref }}' + cancel-in-progress: true steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@master + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | - sudo apt-get update --fix-missing - sudo apt-get autoremove - sudo apt-get autoclean - pip install --user --upgrade setuptools - pip install tox==4.6.3 + pip install 'tox>=4.21,<5' tox-uv - name: Code style check run: | tox -e black-diff @@ -69,29 +71,26 @@ jobs: run: working-directory: ./python continue-on-error: False - needs: - - lock_check runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest] python-version: ["3.9", "3.10", "3.11"] timeout-minutes: 20 + concurrency: + group: 'test:common:${{ matrix.python-version }}:${{ github.ref }}' + cancel-in-progress: true steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 - - uses: actions/setup-python@master + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install Dependencies run: | - sudo apt-get update --fix-missing - sudo apt-get autoremove - sudo apt-get autoclean - pip install --user --upgrade setuptools - pip install tox==4.6.3 + pip install 'tox>=4.21,<5' tox-uv - name: Unittests run: | export COMPOSIO_API_KEY=${{ secrets.COMPOSIO_API_KEY_STAGING }} @@ -99,20 +98,57 @@ jobs: export FLY_API_TOKEN=${{ secrets.FLY_API_TOKEN }} export E2B_API_KEY=${{ secrets.E2B_API_KEY_STAGING }} - tox -e test -- -m 'not e2e' + tox -e test -- -m 'not e2e and not swe' - if: matrix.python-version == '3.10' name: Upload test results to Codecov uses: codecov/test-results-action@v1 with: token: ${{ secrets.CODECOV_TOKEN }} + swe: + defaults: + run: + working-directory: ./python + continue-on-error: False + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest] + python-version: ["3.10"] + timeout-minutes: 20 + concurrency: + group: 'test:swe:${{ matrix.python-version }}:${{ github.ref }}' + cancel-in-progress: true + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 + + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Install Dependencies + run: | + pip install 'tox>=4.21,<5' tox-uv + - name: Unittests + run: | + export COMPOSIO_API_KEY=${{ secrets.COMPOSIO_API_KEY_STAGING }} + export COMPOSIO_BASE_URL=${{ secrets.COMPOSIO_BASE_URL_STAGING }} + export FLY_API_TOKEN=${{ secrets.FLY_API_TOKEN }} + export E2B_API_KEY=${{ secrets.E2B_API_KEY_STAGING }} + + tox -e test -- -m 'swe' + - name: Upload test results to Codecov + uses: codecov/test-results-action@v1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + e2e: defaults: run: working-directory: ./python continue-on-error: False - needs: - - lock_check runs-on: ${{ matrix.os }} strategy: matrix: @@ -120,7 +156,7 @@ jobs: python-version: ["3.10"] timeout-minutes: 15 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 @@ -136,16 +172,12 @@ jobs: sudo systemctl start docker sudo systemctl enable docker - - uses: actions/setup-python@master + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install Dependencies run: | - sudo apt-get update --fix-missing - sudo apt-get autoremove - sudo apt-get autoclean - pip install --user --upgrade setuptools - pip install tox==4.6.3 + pip install 'tox>=4.21,<5' tox-uv - name: Build docker images run: | cd dockerfiles diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 0c5ca85d710..a3499ff7cf0 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -70,8 +70,8 @@ jobs: ] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@master - - uses: actions/setup-python@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Run Tests @@ -85,17 +85,12 @@ jobs: COMPOSIO_BASE_URL: ${{ inputs.base_url || secrets.COMPOSIO_BASE_URL || 'https://backend.composio.dev/api' }} # TODO(@kaavee): Add Anthropic API key run: | - sudo apt-get update --fix-missing - sudo apt-get autoremove - sudo apt-get autoclean - python -m pip install --upgrade pip pipenv pytest python -m pip install plugins/${{matrix.package}} python -m pip install '.[all]' python -m pip install 'numpy<2' python-dotenv python -m pip install unstructured - COMPOSIO_BASE_URL=${{ env.COMPOSIO_BASE_URL }} COMPOSIO_API_KEY=${{ env.COMPOSIO_API_KEY }} COMPOSIO_LOGGING_LEVEL='debug' composio apps update COMPOSIO_BASE_URL=${{ env.COMPOSIO_BASE_URL }} COMPOSIO_API_KEY=${{ env.COMPOSIO_API_KEY }} COMPOSIO_LOGGING_LEVEL='debug' PLUGIN_TO_TEST=${{matrix.package}} CI=false pytest -vv tests/test_example.py COMPOSIO_BASE_URL=${{ env.COMPOSIO_BASE_URL }} COMPOSIO_API_KEY=${{ env.COMPOSIO_API_KEY }} COMPOSIO_LOGGING_LEVEL='debug' PLUGIN_TO_TEST=${{matrix.package}} CI=false pytest -vv tests/test_load_tools.py - name: Slack Notification on Failure diff --git a/.github/workflows/examples_js.yml b/.github/workflows/examples_js.yml new file mode 100644 index 00000000000..c85465a1b05 --- /dev/null +++ b/.github/workflows/examples_js.yml @@ -0,0 +1,90 @@ +name: JS Example Tests + +on: + workflow_call: + inputs: + working-directory: + required: false + type: string + api_key: + required: false + type: string + base_url: + required: false + type: string + author: + required: false + type: string + commit_message: + required: false + type: string + dont_notify: + required: false + type: boolean + workflow_dispatch: + inputs: + working-directory: + required: false + type: string + api_key: + required: false + type: string + base_url: + required: false + type: string + author: + required: false + type: string + commit_message: + required: false + type: string + +jobs: + run-js-tests: + name: Run JS Example Tests + defaults: + run: + working-directory: ${{ inputs.working-directory }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + node-version: ["18"] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + + - name: Install pnpm + run: npm install -g pnpm + + - name: Install Dependencies + run: | + pnpm install @ai-sdk/openai ai composio-core dotenv zod + - name: Run Tests + env: + DOCKER_USER: ${{secrets.DOCKER_USER}} + OPENAI_API_KEY: ${{secrets.OPENAI_API_KEY}} + JULEP_API_KEY: ${{secrets.JULEP_API_KEY}} + JULEP_API_URL: ${{secrets.JULEP_API_URL}} + LISTENNOTES_API_KEY: ${{secrets.LISTENNOTES_API_KEY}} + COMPOSIO_API_KEY: ${{ inputs.api_key || secrets.COMPOSIO_API_KEY_RELEASE }} + COMPOSIO_BASE_URL: 'https://backend.composio.dev' + run: | + pnpm exec jest tests/test_examples.test.js + - name: Slack Notification on Failure + if: ${{ failure() && github.ref == 'refs/heads/master' && !contains(github.event.head_commit.message, 'release') && !contains(github.event.head_commit.message, 'Release') && !inputs.dont_notify }} + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_WEBHOOK: ${{ secrets.SLACK_TECH_WEBHOOK }} + SLACK_TITLE: "JS Example Tests Failed" + SLACK_MSG_AUTHOR: ${{ inputs.author || github.actor }} + SLACK_MESSAGE: "<@Apoorv> <@kaavee> ${{ inputs.commit_message || github.event.head_commit.message }}" + SLACK_LINK_NAMES: "true" + SLACK_COLOR: "failure" + SLACK_USERNAME: "GitHub Actions Bot" + SLACK_ICON_EMOJI: ":x:" + SLACK_FOOTER: "Failed Example Tests | GitHub Actions" \ No newline at end of file diff --git a/.github/workflows/lint_js.yml b/.github/workflows/lint_js.yml new file mode 100644 index 00000000000..1c30a041f7c --- /dev/null +++ b/.github/workflows/lint_js.yml @@ -0,0 +1,42 @@ +name: Check Linting and Formatting (JS) + +on: + push: + paths: + - '**/*.js' + - '**/*.ts' + pull_request: + paths: + - '**/*.js' + - '**/*.ts' + +jobs: + lint-and-prettify: + runs-on: ubuntu-latest + + defaults: + run: + working-directory: js + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install pnpm + run: npm install -g pnpm + + - name: Install packages in js folder + run: pnpm install --frozen-lockfile + + - name: Run ESLint + run: pnpm run eslint + continue-on-error: false + + - name: Run Prettier + run: pnpm run prettier:check + continue-on-error: false \ No newline at end of file diff --git a/.github/workflows/pr_title.yml b/.github/workflows/pr_title.yml new file mode 100644 index 00000000000..5eb4474dfd4 --- /dev/null +++ b/.github/workflows/pr_title.yml @@ -0,0 +1,21 @@ +name: PR Title check + +on: + pull_request: + types: + - opened + - edited + - synchronize + - reopened + +permissions: + pull-requests: read + +jobs: + main: + name: Validate PR title + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index ff0957efaef..fe7670f02a5 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -22,8 +22,8 @@ jobs: python-version: ["3.10"] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@master - - uses: actions/setup-python@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Build @@ -31,10 +31,6 @@ jobs: COMPOSIO_BASE_URL: https://backend.composio.dev/api COMPOSIO_API_KEY: ${{secrets.COMPOSIO_API_KEY_RELEASE}} run: | - sudo apt-get update --fix-missing - sudo apt-get autoremove - sudo apt-get autoclean - # Setup release python -m pip install --upgrade pip python -m pip install . @@ -84,17 +80,13 @@ jobs: ] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Build ${{ matrix.package }} run: | - sudo apt-get update --fix-missing - sudo apt-get autoremove - sudo apt-get autoclean - python -m pip install --upgrade pip pip install twine build # Build dist @@ -121,17 +113,13 @@ jobs: python-version: ["3.10"] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Build run: | - sudo apt-get update --fix-missing - sudo apt-get autoremove - sudo apt-get autoclean - python -m pip install --upgrade pip pip install twine build # Build dist @@ -154,8 +142,8 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout code - uses: actions/checkout@v2 - - uses: actions/setup-python@v3 + uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: "3.10" - name: Build for ${{ matrix.os }} @@ -239,7 +227,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Docker login env: DOCKER_USER: ${{secrets.DOCKER_USER}} @@ -251,7 +239,7 @@ jobs: docker run --privileged --rm tonistiigi/binfmt --install all docker buildx create --use --name multibuild docker buildx inspect --bootstrap - - uses: actions/setup-python@v3 + - uses: actions/setup-python@v5 with: python-version: "3.10" - name: Publishing tool server images @@ -267,7 +255,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - uses: actions/setup-node@v4 - name: Install E2B run: | diff --git a/.github/workflows/release_js_sdk.yml b/.github/workflows/release_js_sdk.yml index 04ce06b9ae0..c4b0935c6be 100644 --- a/.github/workflows/release_js_sdk.yml +++ b/.github/workflows/release_js_sdk.yml @@ -1,16 +1,21 @@ name: Release JS SDK on: - push: - # Pattern matched against refs/tags - # This workflow will run when a tag starting with 'js-' is pushed - # For example, 'js-v1.0.0' or 'js-release-2.3.1' - tags: - - 'js-*' - + workflow_dispatch: + inputs: + version: + description: 'Version to publish (e.g., 0.3.0 | 0.3.0-beta)' + required: true + type: string + isRCRelease: + description: 'Is this a release candidate release?' + required: true + type: boolean jobs: run-js-tests: + permissions: + contents: write timeout-minutes: 60 runs-on: ubuntu-latest @@ -21,14 +26,14 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '20' registry-url: 'https://registry.npmjs.org' - name: Install dependencies - run: npm install -g pnpm@8.15.7 + run: npm install -g pnpm - name: Install packages in js folder - run: pnpm install + run: pnpm install --frozen-lockfile - name: Set publishing config run: pnpm config set '//registry.npmjs.org/:_authToken' "${NODE_AUTH_TOKEN}" @@ -39,5 +44,9 @@ jobs: run: pnpm build - name: pnpm publish - run: pnpm publish --no-git-checks - + run: | + if ${{ github.event.inputs.isRCRelease }}; then + pnpm publish --no-git-checks --tag rc + else + pnpm publish --no-git-checks + fi diff --git a/.github/workflows/run_examples.yml b/.github/workflows/run_examples.yml index 4a6be16aa01..2b98b18f29c 100644 --- a/.github/workflows/run_examples.yml +++ b/.github/workflows/run_examples.yml @@ -4,6 +4,8 @@ on: push: branches: - master + paths: + - 'python/**' jobs: test-examples: diff --git a/.github/workflows/run_examples_js.yml b/.github/workflows/run_examples_js.yml new file mode 100644 index 00000000000..10cba0489d6 --- /dev/null +++ b/.github/workflows/run_examples_js.yml @@ -0,0 +1,22 @@ +# Run examples inside JS folders +name: Run examples JS + +on: + workflow_dispatch: + pull_request: + paths: + - '**/*.js' + - '**/*.ts' + push: + branches: + - master + paths: + - '**/*.js' + - '**/*.ts' + +jobs: + test-examples: + uses: ./.github/workflows/examples_js.yml + with: + working-directory: ./js + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/run_js_test.yml b/.github/workflows/run_js_test.yml index b92c3331443..8b228ead4e4 100644 --- a/.github/workflows/run_js_test.yml +++ b/.github/workflows/run_js_test.yml @@ -4,7 +4,11 @@ on: push: branches: - master + paths: + - 'js/**' pull_request: + paths: + - 'js/**' jobs: @@ -18,17 +22,17 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' - name: Set up Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '20' - name: Install dependencies - run: npm install -g pnpm@8.15.7 + run: npm install -g pnpm - name: Install packages in js folder - run: cd js && pnpm install + run: cd js && pnpm install --frozen-lockfile - name: pnpm build run: cd js && pnpm build - name: run test @@ -37,7 +41,7 @@ jobs: - name: Upload `coverage` folder to R2 if: ${{ always() }} - uses: ryand56/r2-upload-action@latest + uses: himanshu-dixit/r2-upload-action-parallel@v1.3 with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} @@ -53,7 +57,7 @@ jobs: - name: Upload jest html-reporters folder to R2 if: ${{ always() }} - uses: ryand56/r2-upload-action@latest + uses: himanshu-dixit/r2-upload-action-parallel@v1.3 with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} diff --git a/HACKTOBER_FEST_2024.md b/HACKTOBER_FEST_2024.md index f6c626eb1bb..3a209da9503 100644 --- a/HACKTOBER_FEST_2024.md +++ b/HACKTOBER_FEST_2024.md @@ -35,7 +35,7 @@ Composio is a cutting-edge toolset for AI Agents and LLMs, designed to streamlin - πŸ” **Managed Auth**: Built-in auth management for less developer overhead - πŸ“ˆ **30% increase in reliability**: Simplified JSON structures, improved variable names, and enhanced error handling - πŸ€– **Powerful RPA tools**: Spin up MacOS/Ubuntu instances on-the-fly for agent control and remote code execution -- πŸ”’ **SOC Type 2**: 100% compliant with maximum data security +- πŸ”’ **SOC 2 Type 2**: 100% compliant with maximum data security - 🏠 **Self Hosting**: One-click installation across all platforms ## πŸŽ‰ Hacktoberfest 2024 Participation diff --git a/docs/examples/combined/calendar-agent.mdx b/docs/examples/combined/calendar-agent.mdx index 16009e12429..69bb1555c54 100644 --- a/docs/examples/combined/calendar-agent.mdx +++ b/docs/examples/combined/calendar-agent.mdx @@ -54,7 +54,7 @@ description: "This project is an example which uses Composio to seamlessly conve composio_toolset = ComposioToolSet() tools = composio_toolset.get_tools(apps=[App.GOOGLECALENDAR]) - # Retreive the current date and time + # Retrieve the current date and time date = datetime.today().strftime("%Y-%m-%d") timezone = datetime.now().astimezone().tzinfo ``` @@ -240,7 +240,7 @@ description: "This project is an example which uses Composio to seamlessly conve composio_toolset = ComposioToolSet() tools = composio_toolset.get_tools(apps=[App.GOOGLECALENDAR]) - # Retreive the current date and time + # Retrieve the current date and time date = datetime.today().strftime("%Y-%m-%d") timezone = datetime.now().astimezone().tzinfo diff --git a/docs/faq/integrations_and_connections/connections.mdx b/docs/faq/integrations_and_connections/connections.mdx deleted file mode 100644 index 376afd3d001..00000000000 --- a/docs/faq/integrations_and_connections/connections.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: "Listing Connected Accounts in Composio" -sidebarTitle: "Listing Connected Accounts" -icon: "user" -description: "Managing and monitoring your connections is essential to show your users what integrations they have connected." ---- - -### Listing All Connections for an Entity -To view all the connections associated with your Composio account, use the following command: - -```python Python Connections for a User -from composio_openai import ComposioToolSet - -tool_set = ComposioToolSet() - -entity = tool_set.get_entity(id="entity_id") - -print(entity.get_connections()) -``` - -```javascript Javascript Connections for a User -import { OpenAIToolSet } from "composio-core"; - -const toolset = new OpenAIToolSet({}); - -const entity = await toolset.client.getEntity("default"); - -console.log(await entity.getConnections()); -``` - - -### Getting Connection Details -To get detailed information about a specific connection, use the get command followed by the connection ID. For example, to get details of a connection with the ID 123, you would use: - - -```python Python Get connection details -from composio_openai import ComposioToolSet, App - -tool_set = ComposioToolSet() - -connected_account = tool_set.get_connected_account(id="connected_account_id") -``` - -```javascript Javascript Get connection details -import { Composio } from "composio-core"; -// get composio client -const composio = new Composio(); - -const connected_account = await composio.connectedAccounts.get({ - connectedAccountId: "connected_account_id", -}); -``` - diff --git a/docs/faq/integrations_and_connections/integrations.mdx b/docs/faq/integrations_and_connections/integrations.mdx deleted file mode 100644 index 2dfadc3b9c2..00000000000 --- a/docs/faq/integrations_and_connections/integrations.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: "Listing Integrations in Composio" -sidebarTitle: "Listing Integrations" -icon: "user" -description: "This page will help you manage integrations in Composio" ---- - -### Listing All Integrations -To retrieve a complete list of your integrations, you can use the following code snippets. - - -```python Python List all integrations -from composio_openai import ComposioToolSet, App - -tool_set = ComposioToolSet() - -integrations = tool_set.get_integrations() -``` - -```javascript Javascript List all integrations -import {Composio} from "composio-core"; - -// get composio client -const composio = new Composio(); - -const integrations = await composio.integrations.list({}) -``` - - -This command will display a comprehensive list of all integrations - -### Getting Integration Details -To get detailed information about a specific integration, use the get command followed by the integration ID. For example, to get details of a connection with the ID 123, you would use: - - -```python Python Get integration details -from composio import ComposioToolSet - -tool_set = ComposioToolSet() - -integration = tool_set.get_integration(id="integration_id") -``` - -```javascript Javascript Get integration details -import { Composio } from "composio-core"; - -// get composio client -const composio = new Composio(); - -const integration = await composio.integrations.get({ - integrationId: "integration_id", -}); -``` - \ No newline at end of file diff --git a/docs/faq/supported_llms/supported_llm.mdx b/docs/faq/supported_llms/supported_llm.mdx index b5e25771b36..d3a3c1f30a9 100644 --- a/docs/faq/supported_llms/supported_llm.mdx +++ b/docs/faq/supported_llms/supported_llm.mdx @@ -54,142 +54,6 @@ console.log(completion.choices[0].message.content) ``` - - - -```python Python -import dotenv -from composio_google import App, ComposioToolset -from vertexai.generative_models import GenerativeModel - -# Load environment variables from .env -dotenv.load_dotenv() - -# Initialize the Composio Toolset -composio_toolset = ComposioToolset() - -# Get GitHub tools that are pre-configured -tool = composio_toolset.get_tool(apps=[App.GITHUB]) - -# Initialize the Google AI Gemini model -model = GenerativeModel("gemini-1.5-pro", tools=[tool]) - -# Start a chat session -chat = model.start_chat() - -# Define task -task = "Star a repo composiohq/composio on GitHub" - -# Send a message to the model -response = chat.send_message(task) - -print("Model response:") -print(response) - -result = composio_toolset.handle_response(response) -print("Function call result:") -print(result) - -``` - - - - - -```python Python -import dotenv -from composio_claude import App, ComposioToolset -import anthropic - -# Load environment variables from .env -dotenv.load_dotenv() - -# Initialize the Composio Toolset -composio_toolset = ComposioToolset() - -# Get GitHub tools that are pre-configured -tool = composio_toolset.get_tool(apps=[App.GITHUB]) - -# Initialize the Google AI Gemini model -client = anthropic.Anthropic() - -my_task = "Star a repo composiohq/composio on GitHub" - -# Create a chat completion request to decide on the action -response = client.beta.tools.messages.create( - model="claude-3-opus-20240229", - max_tokens=1024, - tools= actions, - messages=[{"role": "user", "content": "Star me composiohq/composio repo in github."}], -) -print(response) - -result = toolset.handle_tool_calls(response) -print(result) -``` - - - -```python Python -import os - -from composio_openai import App, ComposioToolSet -import groq - -tool_set = ComposioToolSet() -tools = tool_set.get_tools(apps=[App.TAVILY]) - -groq_client = groq.Groq(api_key=os.environ.get("GROQ_API_KEY")) -system_prompt = """You are a helpful assistant. -whenever appropriate, use the Tavily search tool for the latest -information from the internet to provide users with up-to-date information. -Return the URL of the information. -""" - -user_prompt = "Who was the gold medalist in Men's 100m sprint in paris olymics, 2024?" - -messages=[ - { - "role": "system", - "content": system_prompt - }, - { - "role": "user", - "content": user_prompt, - } -] - -response = groq_client.chat.completions.create( - model="llama-3.1-70b-versatile", - messages=messages, - tools=tools, - tool_choice="auto", - max_tokens=4096 -) -response_message = response.choices[0].message -tool_call_id = response_message.tool_calls[0].id -tool_name = response_message.tool_calls[0].function.name -# Execute function calls -response_after_tool_calls = tool_set.handle_tool_calls(response=response) - -content = response_after_tool_calls[0]['data']['response_data']['results'][0]['content'] -url = response_after_tool_calls[0]['data']['response_data']['results'][0]['url'] - -messages.append({ - "tool_call_id": tool_call_id, - "role": "tool", - "name": tool_name, - "content": f"{content}+url:+{url}", - }) -second_response = groq_client.chat.completions.create( - model="llama-3.1-70b-versatile", - messages=messages -) -print(second_response.choices[0].message.content) - -``` - - ```python Python import os diff --git a/docs/framework/autogen.mdx b/docs/framework/autogen.mdx index 11e05efff77..93d6213e128 100644 --- a/docs/framework/autogen.mdx +++ b/docs/framework/autogen.mdx @@ -2,145 +2,61 @@ title: "Using Composio With Autogen" sidebarTitle: "Autogen" icon: "robot" -description: "Integrate Composio with Autogen agents to let them seamlessly interact with external apps" +description: "Integrate Composio with Autogen agents to let them seamlessly interact with external Apps" --- -**Composio enables** your **Autogen agents** to **connect** with many **tools**! - -### Install Packages & Connect a Tool - - - Goal: Star a repository on GitHub with natural language & Autogen Agent - - -These commands prepare your environment for seamless interaction between Autogen and Github. - - - ```bash Run Command - pip install composio-autogen - ``` - +## Star A Repository on Github +In this example, we will use Autogen Agent to star a repository on Github using Composio Tools - - - -- Connect a user Jessica's Github account to allow your agents to utilize GitHub functionalities. - - - -```bash Authenticate GitHub Account -composio add github -e "Jessica" + +```bash Python +pip install composio-autogen ``` - - - - -```python Authenticate Jessica's GitHub Account + + +```bash Python +from autogen import AssistantAgent, UserProxyAgent from composio_autogen import ComposioToolSet, App -toolset = ComposioToolSet(entity_id="Jessica") - -entity = toolset.get_entity() - -request = entity.initiate_connection(App.GITHUB) - -print( - f"Open this URL in your browser: {request.redirectUrl}" -) +toolset = ComposioToolSet(api_key="") +llm_config = { + "config_list": [ + { + "model": "gpt-4o-mini", + "api_key": "", + } + ] +} ``` - - - - - - - - ```python Default Imports & Configuration - from autogen import AssistantAgent, UserProxyAgent - import os - - llm_config = {"config_list": [{"model": "gpt-4-turbo", "api_key": os.environ["OPENAI_API_KEY"]}]} - - chatbot = AssistantAgent( - "chatbot", - system_message="Reply TERMINATE when the task is done or when user's content is empty", - llm_config=llm_config, - ) - - # create a UserProxyAgent instance named "user_proxy" - user_proxy = UserProxyAgent( - "user_proxy", - is_termination_msg=lambda x: x.get("content", "") and "TERMINATE" in x.get("content", ""), - human_input_mode="NEVER", # Don't take input from User - code_execution_config = {"use_docker": False} - ) - ``` - - - - - - ```python Tools For Github - # Import from composio_autogen - from composio_autogen import ComposioToolSet, App, Action - - # Initialise the Composio Tool Set - - composio_toolset = ComposioToolSet(entity_id="Jessica") - - # Register the preferred Applications, with right executor. - - composio_toolset.register_tools(tools=[App.GITHUB],caller=chatbot, executor=user_proxy) - ``` - - - - ```python Autogen Agent executes the task - task = "Star a repo composiohq/composio on GitHub" - - response = user_proxy.initiate_chat(chatbot,message=task) + +You can get all the tools for a given app as shown below, but you can get **specific actions** and filter actions using **usecase** & **tags**. Learn more [here](../../patterns/tools/use-tools/use-specific-actions) +```python Python +chatbot = AssistantAgent( + "chatbot", + system_message="Reply TERMINATE when the task is done or when user's content is empty", + llm_config=llm_config, +) - print(response.chat_history) - ``` +user_proxy = UserProxyAgent( + name="User", + is_termination_msg=lambda x: x.get("content", "") + and "TERMINATE" in x.get("content", ""), + human_input_mode="NEVER", + code_execution_config={"use_docker": False}, +) - +toolset.register_tools(apps=[App.GITHUB], caller=chatbot, executor=user_proxy) +``` - - - ```bash Executing Agents - [{'content': 'I have starred the repository "docs" for you on GitHub under the account "composiohq".', 'role': 'user'}, - {'content': '', 'role': 'assistant'}, {'content': 'TERMINATE', 'role': 'user'}] - ``` - - + +```python Python +task = "Star a repo composiohq/composio on GitHub" +response = user_proxy.initiate_chat(chatbot, message=task) +print(response.chat_history) +``` - -### Use Specific Actions - - ```bash Filter Specific Action - # To restrict agents from using all the actions, filter specific actions - composio_toolset.register_actions(actions=[Action.GITHUB_CREATE_ISSUE]) - ``` - - -### Use Specific Apps - - - ```bash Filter Specific App - # To restrict agents from using all tools, filter specific tools - composio_toolset.register_tools(apps=[App.ASANA, App.GITHUB]) - ``` - - -### Filter apps actions by tags - - - ```bash Filter Actions by Tags - # To restrict agents from using all actions, filter the actions by tags - composio_toolset.register_tools(apps=[App.ASANA], tags=[Tag.ASANA_TASKS]) - ``` - + \ No newline at end of file diff --git a/docs/framework/crewai.mdx b/docs/framework/crewai.mdx index b7c8b2aeb11..edbca689dd3 100644 --- a/docs/framework/crewai.mdx +++ b/docs/framework/crewai.mdx @@ -2,163 +2,66 @@ title: "Using Composio With CrewAI" sidebarTitle: "CrewAI" icon: "people-group" -description: "Integrate Composio with Crewai agents to let them seamlessly interact with external apps" +description: "Integrate Composio with CrewAI agents to let them seamlessly interact with external apps" --- -CrewAI Logo - -**Composio enables** your **CrewAI agents** to **connect** with many **tools**! - - - Goal: Star a repository on GitHub with natural language & CrewAI Agent - - -### Install Packages & Connect a Tool - -These commands prepare your environment for seamless interaction between CrewAI and Github. - - -```bash Run Command -pip install composio_crewai -``` - - - -### Goal: Use Crew Agent to Interact with Github using Composio +## Star A Repository on Github +In this example, we will use CrewAI Agent to star a repository on Github using Composio Tools - -- Connect a user Jessica's Github account to allow our agents to utilize GitHub functionalities. - - - -```bash Authenticate GitHub Account -composio add github -e "Jessica" -``` - - - - -```python Authenticate Jessica's GitHub Account -from composio_crewai import ComposioToolSet, App - -toolset = ComposioToolSet(entity_id="Jessica") - -entity = toolset.get_entity() - -request = entity.initiate_connection(App.GITHUB) - -print( - f"Open this URL in your browser: {request.redirectUrl}" -) + +```bash Python +pip install composio_crewai crewai langchain_openai ``` - - - - - - - - -```python Default Imports + +```bash Python +from composio_crewai import ComposioToolSet, App from crewai import Agent, Task, Crew from langchain_openai import ChatOpenAI -# add OPENAI_API_KEY to env variables. -llm = ChatOpenAI() +toolset = ComposioToolSet(api_key="") +llm = ChatOpenAI(api_key="") ``` - - - - + +You can get all the tools for a given app as shown below, but you can get **specific actions** and filter actions using **usecase** & **tags**. Learn more [here](../../patterns/tools/use-tools/use-specific-actions) -```python Tools For Github - -from composio_crewai import ComposioToolSet, Action, App - -# Get All the tools - -composio_toolset = ComposioToolSet(entity_id="Jessica") -tools = composio_toolset.get_tools(apps=[App.GITHUB]) +```python Python +tools = toolset.get_tools(apps=[App.GITHUB]) ``` - - - - -```python CrewAI Agent Executes Task -# Define agent + +```python Python crewai_agent = Agent( role="Github Agent", - goal="""You take action on Github using Github APIs""", - backstory=( - "You are AI agent that is responsible for taking actions on Github " - "on users behalf. You need to take action on Github using Github APIs" - ), + goal="You take action on Github using Github APIs", + backstory="You are AI agent that is responsible for taking actions on Github on behalf of users using Github APIs", verbose=True, tools=tools, llm=llm, ) + task = Task( description="Star a repo composiohq/composio on GitHub", agent=crewai_agent, - expected_output="if the star happened" + expected_output="Status of the operation" ) -my_crew = Crew(agents=[crewai_agent], tasks=[task]) -result = my_crew.kickoff() -print(result) +crew = Crew( + agents = [crewai_agent], + tasks = [task] +) ``` - - - - - -```bash Executing Agents -> Entering new CrewAgentExecutor chain...[0m -I need to star a repository on GitHub, specifically the repo "composiohq/composio". - -Action: -github_star_repo - -Action Input: -{ -"owner": "composiohq", -"repo": "composio" -} - -{'execution_details': {'executed': True}, 'response_data': ''} -Final Answer: {'execution_details': {'executed': True}, 'response_data': ''}[0m - -> Finished chain.[0m -> {'execution_details': {'executed': True}, 'response_data': ''} + +```python Python +result = crew.kickoff() +print(result) ``` - - - -### Use Specific Actions - - ```bash Filter Specific Action - # To restrict agents from using all the actions, filter specific actions - composio_toolset = ComposioToolSet() - tools = composio_toolset.get_tools(actions=[Action.GITHUB_CREATE_ISSUE]) - ``` - - -### Use Specific Apps - - - ```bash Filter Specific App - # To restrict agents from using all tools, filter specific tools - composio_toolset = ComposioToolSet() - tools = composio_toolset.get_tools(apps=[App.GITHUB]) - ``` - + \ No newline at end of file diff --git a/docs/framework/google.mdx b/docs/framework/google.mdx index 6b9d3dc00a2..7ce47a677bc 100644 --- a/docs/framework/google.mdx +++ b/docs/framework/google.mdx @@ -1,7 +1,7 @@ --- title: "Using Composio With Google AI" sidebarTitle: "Google AI" -icon: "robot" +icon: "google" description: "Enable Google AI models to seamlessly interact with external apps via Composio for enhanced functionality" --- diff --git a/docs/framework/groq.mdx b/docs/framework/groq.mdx index 66b1776c721..8f03b61ba8f 100644 --- a/docs/framework/groq.mdx +++ b/docs/framework/groq.mdx @@ -2,13 +2,13 @@ title: "πŸ¦œπŸ”— Using Composio With Groq" sidebarTitle: "Groq" icon: "link" -description: "Integrate Composio with Groq based assistants to let them seamlessly interact with external apps" +description: "Integrate Composio with Groq to seamlessly interact with external apps" --- -**Composio enables** your **Groq LLM based assistants** to **connect** with many **tools**! +**Composio enables** your **Groq based assistants** to **connect** with many **tools**! - Goal: Star a repository on GitHub with natural language & Groq LLM based assistant + Goal: Star a repository on GitHub with natural language & Groq ### Install Packages & Connect a Tool diff --git a/docs/framework/langchain.mdx b/docs/framework/langchain.mdx index 0be0939ffe0..ba983f128d7 100644 --- a/docs/framework/langchain.mdx +++ b/docs/framework/langchain.mdx @@ -2,156 +2,89 @@ title: "πŸ¦œπŸ”— Using Composio With LangChain" sidebarTitle: "LangChain" icon: "link" -description: "Integrate Composio with Langchain agents to let them seamlessly interact with external apps" +description: "Integrate Composio with LangChain agents to let them seamlessly interact with external apps" --- -**Composio enables** your **Langchain agents** to **connect** with many **tools**! - - - Goal: Star a repository on GitHub with natural language & Langchain Agent - - -### Install Packages & Connect a Tool - -These commands prepare your environment for seamless interaction between Langchain and Github. - - - ```bash python - pip install composio-langchain - - #Connect your Github so agents can use it - composio add github - - #Check all different apps which you can connect with - composio apps - ``` - ```javascript javascript - npm install composio-core - npm install langchain - - // Connect your Github so agents can use it - composio add github - - // Check all different apps which you can connect with - composio apps - ``` - +## Star A Repository on Github +In this example, we will use LangChain Agent to star a repository on Github using Composio Tools - + - ```python python - # Initialise imports - from langchain.agents import create_openai_functions_agent, AgentExecutor - from langchain import hub - from langchain_openai import ChatOpenAI - - - llm = ChatOpenAI() - - prompt = hub.pull("hwchase17/openai-functions-agent") - ``` - ```javascript javascript - // Importing necessary modules from langchain and composio-core packages - import dotenv from 'dotenv'; - dotenv.config(); - - import { ChatOpenAI } from "@langchain/openai"; - import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; - import { LangchainToolSet } from "composio-core"; - import { pull } from "langchain/hub"; - - // Creating an instance of ChatOpenAI with specific model and temperature settings - const llm = new ChatOpenAI({ - model: "gpt-3.5-turbo", - temperature: 0, - }); - - // Pulling a chat prompt template asynchronously using the pull function - const prompt = await pull( - "hwchase17/openai-functions-agent" - ); - ``` +```bash Python +pip install composio-langchain langchain_openai +``` +```javascript JavaScript +npm install composio-core langchain @langchain/openai +``` - + - ```python python - # Import from composio_langchain - from composio_langchain import ComposioToolSet, Action, App - - # Get All the tools - - composio_toolset = ComposioToolSet() - tools = composio_toolset.get_tools(apps=[App.GITHUB]) - ``` - - ```javascript javascript - // Initialize the LangchainToolSet with the API key from environment variables - const toolset = new LangchainToolSet({ apiKey: process.env.COMPOSIO_API_KEY}); - - // Fetch tools configured for GitHub applications - const tools = await toolset.getTools({ apps: ["github"] }); - ``` +```python Python +from langchain.agents import create_openai_functions_agent, AgentExecutor +from langchain import hub +from langchain_openai import ChatOpenAI +from composio_langchain import ComposioToolSet, App + +llm = ChatOpenAI() +composio_toolset = ComposioToolSet() +``` +```javascript JavaScript +import { ChatOpenAI } from "@langchain/openai"; +import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; +import { LangchainToolSet } from "composio-core"; +import { pull } from "langchain/hub"; + +const llm = new ChatOpenAI(); +const toolset = new LangchainToolSet(); +``` - -Create an agent, set up an executor, and invoke tasks to perform GitHub API calls using Composio. - - ```python python - task = "Star a repo composiohq/composio on GitHub" - - agent = create_openai_functions_agent(llm, tools, prompt) - agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) - - # Execute using agent_executor - agent_executor.invoke({"input": task}) - ``` - ```javascript javascript - // Create an OpenAI functions agent with the provided LLM, tools, and prompt - const agent = await createOpenAIFunctionsAgent({ - llm, - tools: tools, - prompt, - }); - - // Initialize the agent executor with verbosity enabled - const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); - // Invoke the agent to perform the task of starring a GitHub repository - const response = await agentExecutor.invoke({ input: "Star a repo composiohq/composio on GitHub" }); - - // Output the response from the agent execution - console.log(response); - ``` + +You can get all the tools for a given app as shown below, but you can get **specific actions** and filter actions using **usecase** & **tags**. Learn more [here](../../patterns/tools/use-tools/use-specific-actions) + +```python Python +tools = composio_toolset.get_tools(apps=[App.GITHUB]) +``` +```javascript JavaScript +const tools = await toolset.getTools({ apps: ["github"] }); +``` - - - ```bash Executing Agents - > Entering new AgentExecutor chain... - - Invoking: `github_star_repo` with `{'owner': 'composiohq', 'repo': 'docs'}` - {'connectedAccountId': 'ade8c167-836b-404b-bb47-fb8550203417', 'input': {'owner': 'composiohq', 'repo': 'docs'}} - {'execution_details': {'executed': True}, 'response_data': ''}I have successfully starred the repository composiohq/composio on GitHub. - - ``` - - -### Use Specific Apps + - ```bash Filter Specific App - # To restrict agents from using all the actions, filter specific actions - tools = composio_toolset.get_tools(apps=[App.GITHUB]) - ``` +```python Python +prompt = hub.pull("hwchase17/openai-functions-agent") +agent = create_openai_functions_agent(llm, tools, prompt) +agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) +``` +```javascript JavaScript +const prompt = await pull( + "hwchase17/openai-functions-agent" +); +const agent = await createOpenAIFunctionsAgent({ + llm, + tools: tools, + prompt, +}); +const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); +``` + -### Use Specific Actions - + - ```bash Filter Specific Actions - # To restrict agents from using all tools, filter specific tools - tools = composio_toolset.get_tools(actions=[Action.GITHUB_CREATE_ISSUE]) - ``` +```python Python +task = "Star a repo composiohq/composio on GitHub" +agent_executor.invoke({"input": task}) +``` +```javascript JavaScript +const response = await agentExecutor.invoke({ input: "Star a repo composiohq/composio on GitHub" }); +console.log(response); +``` + + diff --git a/docs/framework/langflow.mdx b/docs/framework/langflow.mdx new file mode 100644 index 00000000000..b858291fff1 --- /dev/null +++ b/docs/framework/langflow.mdx @@ -0,0 +1,57 @@ +--- +title: "Using Composio With LangFlow" +sidebarTitle: "LangFlow" +icon: "network-wired" +description: "Use Composio with LangFlow to create LLM agents that can interact with external apps" +--- + +## Star A Repository on Github +In this example, we will use LangFlow to star a repository on Github using Composio Tools + + + +Head over to the [LangFlow](https://astra.datastax.com/langflow) website, create a new project, look for Composio component in the component list and add it to your project + + + + +Go to your [Composio Dashboard](https://app.composio.dev/) and copy your API key, paste it in the API Key field in the Composio component and then search for Github in apps list and select it + + + + +Click on refresh button, a link to authenticate with Github will be generated (if you don't have connected Github account), click on it and authenticate + +Most recent connected Github account with entity Id `default` will be considered for executing the action + + + + + +After authenticating, click on the refresh button to verify connection status + + + +Select the action `GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER` and you're done configuring the Composio component + + + +Look for agent in Components list, add it to your project, connect Composio component as tools to the agent then configure the agent (model provider, model name, api key, etc.). + + +Lastly modify the agent input to **Star the repo composiohq/composio** + + + +Look for chat output in Components list, add it to your project, connect agent's response to the chat output component. We will use this component to monitor the agent's response + + + +Click on the run button on chat output to run the agent, and open playground to monitor the agent's response + + + +Hurray! You have successfully starred the repository composiohq/composio + + + diff --git a/docs/framework/langgraph.mdx b/docs/framework/langgraph.mdx index 87cf5d84b6a..306c3130616 100644 --- a/docs/framework/langgraph.mdx +++ b/docs/framework/langgraph.mdx @@ -2,150 +2,125 @@ title: "πŸ¦œπŸ•ΈοΈ Using Composio With LangGraph" sidebarTitle: "LangGraph" icon: "spider-web" -description: "Integrate Composio with LangGraph Agentic workfows & enable them to interact seamlessly with external apps, enhancing their functionality and reach." +description: "Integrate Composio with LangGraph agents to let them seamlessly interact with external apps" --- -**Composio enables** your **LangGraph agents** to **connect** with many **tools**! - - - Goal: Star a repository on GitHub using natural language commands through a LangGraph Agent. - - -### Install Packages & Connect a Tool - -Ensure you have the necessary packages installed and connect your GitHub account to allow your agents to utilize GitHub functionalities. - - - ``` bash Run command - pip install composio-langgraph - # login to composio - composio login - ``` - - -### Goal: Use LangGraph Agent to Interact with Github using Composio +## Star A Repository on Github +In this example, we will use LangGraph Agent to star a repository on Github using Composio Tools - - -- Connect user `Jessica` GitHub account to allow your agents to utilize GitHub functionalities. - - + -```bash Authenticate GitHub Account -composio add github -e "Jessica" +```bash Python +pip install composio-langgraph ``` - - - - -```python Authenticate GitHub Account -from composio_langgraph import ComposioToolSet, App - -toolset = ComposioToolSet(entity_id="Jessica") - -entity = toolset.get_entity() - -request = entity.initiate_connection(App.GITHUB) - -print( - f"Open this URL in your browser: {request.redirectUrl}" -) +```bash TypeScript +npm i @langchain/langgraph +npm i composio-core +npm i @langchain/openai +npm i @langchain/core ``` - - - - - -- Prepare your environment by initializing necessary imports from LangGraph & LangChain for setting up your agent. - + +You can get all the tools for a given app as shown below, but you can get **specific actions** and filter actions using **usecase** & **tags**. Learn more [here](../../patterns/tools/use-tools/use-specific-actions) -```python Default Imports +```python Python from typing import Literal - from langchain_openai import ChatOpenAI from langgraph.graph import MessagesState, StateGraph from langgraph.prebuilt import ToolNode -``` - - - +from composio_langgraph import Action, ComposioToolSet, App - - -- Access GitHub tools provided by Composio for LangGraph, initialize a `ToolNode` with necessary tools obtained from `ComposioToolSet`. - - -```python Get tools -from composio_langgraph import Action, ComposioToolSet - -# Initialize the toolset for GitHub -composio_toolset = ComposioToolSet(entity_id="Jessica") +composio_toolset = ComposioToolSet() tools = composio_toolset.get_tools( - actions=[ - Action.GITHUB_ACTIVITY_STAR_REPO_FOR_AUTHENTICATED_USER, - Action.GITHUB_USERS_GET_AUTHENTICATED, - ]) + apps=[App.GITHUB] +) + tool_node = ToolNode(tools) + +model = ChatOpenAI(temperature=0, streaming=True) +model_with_tools = model.bind_tools(tools) ``` - +```typescript TypeScript +import { LangGraphToolSet } from "composio-core"; +import { ToolNode } from "@langchain/langgraph/prebuilt"; +import { ChatOpenAI } from "@langchain/openai"; +import { StateGraph, END, MessagesAnnotation, START } from "@langchain/langgraph"; +import { HumanMessage } from "@langchain/core/messages"; - +const composioToolset = new LangGraphToolSet(); - +const tools = await composioToolset.getTools({ + apps: ["github"], +}); -- Initialize the LLM class and bind obtained functions to the model. +const toolNode = new ToolNode(tools); - - ```python Define model - model = ChatOpenAI(temperature=0, streaming=True) - model_with_tools = model.bind_tools(tools) - ``` +const model = new ChatOpenAI({ temperature: 0, apiKey:""}).bindTools(tools); +``` - - - - -- LangGraph expects you to define different nodes of the agentic workflow as separate functions. - + -```python Define nodes +```python Python def call_model(state: MessagesState): + """ + Process messages through the LLM and return the response + """ messages = state["messages"] response = model_with_tools.invoke(messages) return {"messages": [response]} ``` +```typescript TypeScript +async function callModal(state) { + const { messages } = state; + const response = await model.invoke(messages); + return { messages: [response] }; +} +``` - - - - -- We begin by initializing the workflow with `agent` and `tools` nodes, followed by specifying the connecting edges between nodes, finally compiling the workflow. - -- These edges can be straightforward or conditional, depending on the workflow requirements. - + -```python Define edges +```python Python def should_continue(state: MessagesState) -> Literal["tools", "__end__"]: + """ + Determine if the conversation should continue to tools or end + Returns: + - "tools" if the last message contains tool calls + - "__end__" otherwise + """ messages = state["messages"] last_message = messages[-1] if last_message.tool_calls: return "tools" return "__end__" +``` +```typescript TypeScript +async function shouldContinue(state) { + const { messages } = state; + const lastMessage = messages[messages.length - 1]; + + if (lastMessage.additional_kwargs.tool_calls) { + return "tools"; + } else { + return END; + } +} +``` + + - + + +```python Python workflow = StateGraph(MessagesState) -# Define the two nodes we will cycle between workflow.add_node("agent", call_model) workflow.add_node("tools", tool_node) - workflow.add_edge("__start__", "agent") workflow.add_conditional_edges( "agent", @@ -155,25 +130,28 @@ workflow.add_edge("tools", "agent") app = workflow.compile() ``` +```typescript TypeScript +const workflow = new StateGraph(MessagesAnnotation) + .addNode("agent", callModal) + .addEdge(START, "agent") + .addNode("tools", toolNode) + .addConditionalEdges("agent", shouldContinue) + .addEdge("tools", "agent"); + +const app = workflow.compile(); +``` - - - - - -- After the compilation of workflow, we invoke the LLM with a task, and stream the response. - + -```python Execute workflow +```python Python for chunk in app.stream( { "messages": [ ( "human", - # "Star the Github Repository composiohq/composio", - "Get my information.", + "Star the Github Repository composiohq/composio", ) ] }, @@ -181,7 +159,15 @@ for chunk in app.stream( ): chunk["messages"][-1].pretty_print() ``` +```typescript TypeScript +const stream = await app.invoke({ + messages: [ + new HumanMessage("Star the Github Repository composiohq/composio"), + ], +}); + +console.log(stream.messages[stream.messages.length - 1].content); +``` - diff --git a/docs/framework/litellm.mdx b/docs/framework/litellm.mdx new file mode 100644 index 00000000000..7ec485ca5bd --- /dev/null +++ b/docs/framework/litellm.mdx @@ -0,0 +1,66 @@ +--- +title: "Using Composio With LiteLLM" +sidebarTitle: "LiteLLM" +icon: "people-group" +description: "Integrate Composio with LiteLLM and seamlessly interact with external apps" +--- + +## Star A Repository on Github +In this example, we will use LiteLLM to star a repository on Github using Composio Tools + + + +```bash Python + pip install composio_openai litellm +``` + + +```bash Python +from composio_openai import ComposioToolSet, App +from litellm.router import Router + +toolset = ComposioToolSet() + +router = Router( + model_list=[ + { + "model_name": "anthropic/claude-3-5", + "litellm_params": { + "model": "claude-3-opus-20240229", + "api_key": "", + }, + } + ] +) +``` + + + +You can get all the tools for a given app as shown below, but you can get **specific actions** and filter actions using **usecase** & **tags**. Learn more [here](../../patterns/tools/use-tools/use-specific-actions) + +```python Python +tools = toolset.get_tools(apps=[App.GITHUB]) +``` + + + + +```python Python +response = router.completion( + model="anthropic/claude-3-5", + messages=[ + {"role": "user", "content": "Star the repository composiohq/composio on github"}, + ], + tools=tools, + tool_choice="auto", +) +``` + + + +```python Python +result = toolset.handle_tool_calls(response=response) +print(result) +``` + + \ No newline at end of file diff --git a/docs/framework/llamaindex.mdx b/docs/framework/llamaindex.mdx index 1cc48b413ef..61ed88795f5 100644 --- a/docs/framework/llamaindex.mdx +++ b/docs/framework/llamaindex.mdx @@ -2,137 +2,87 @@ title: "πŸ¦™ Using Composio With LlamaIndex" sidebarTitle: "LlamaIndex" icon: "dove" -description: "Integrate Composio with LlamaIndex application to let them seamlessly interact with external apps" +description: "Integrate Composio with LLamaIndex agents to let them seamlessly interact with external apps" --- -**Composio enables** your **LlamaIndex apps** to **connect** with many useful **tools**! - - - Goal: Star a repository on GitHub with natural language & LlamaIndex agent. - - -### Install Packages & Connect a Tool - -These commands prepare your environment for seamless interaction between LlamaIndex and Github. - - - ```bash Run Command - pip install composio-llamaindex - ``` - +## Star A Repository on Github +In this example, we will use LLamaIndex Agent to star a repository on Github using Composio Tools - - -- Connect a user Jessica's Github account to allow your agents to utilize GitHub functionalities. - - + -```bash Authenticate GitHub Account -composio add github -e "Jessica" +```bash Python +pip install composio-llamaindex llama-index +``` +```typescript Typescript +coming soon ``` - - + + -```python Authenticate Jessica's GitHub Account -from composio_llamaindex import ComposioToolSet, App - -toolset = ComposioToolSet(entity_id="Jessica") - -entity = toolset.get_entity() - -request = entity.initiate_connection(App.GITHUB) - -print( - f"Open this URL in your browser: {request.redirectUrl}" -) +```python Python +from llama_index.llms.openai import OpenAI +from llama_index.core.llms import ChatMessage +from llama_index.core.agent import FunctionCallingAgentWorker +from composio_llamaindex import App, ComposioToolSet + +toolset = ComposioToolSet() +llm = OpenAI() +``` +```typescript Typescript +coming soon ``` - - - + +You can get all the tools for a given app as shown below, but you can get **specific actions** and filter actions using **usecase** & **tags**. Learn more [here](../../patterns/tools/use-tools/use-specific-actions) - ```python Default Imports - # Initialise imports - import dotenv - from llama_index.llms.openai import OpenAI - from llama_index.core.llms import ChatMessage - from llama_index.core.agent import FunctionCallingAgentWorker - - # Load environment variables from .env - dotenv.load_dotenv() - - llm = OpenAI(model="gpt-4o") - ``` - +```python Python +tools = toolset.get_tools(apps=[App.GITHUB]) +``` +```typescript Typescript +coming soon +``` - - - - ```python Tools For Github - # Import from composio_llamaindex - from composio_llamaindex import Action, ComposioToolSet - - # Get All the tools - composio_toolset = ComposioToolSet(entity_id="Jessica") - tools = composio_toolset.get_tools(apps=[App.GITHUB]) - ``` - - -Create a worker agent, setting it up with proper prefix messages and tools. + - ```python Langchain Agent executes the task - prefix_messages = [ - ChatMessage( - role="system", - content=( - "You are now a integration agent, and what ever you are requested, you will try to execute utilizing your toools." - ), - ) - ] - - agent = FunctionCallingAgentWorker( - tools=tools, - llm=llm, - prefix_messages=prefix_messages, - max_function_calls=10, - allow_parallel_tool_calls=False, - verbose=True, - ).as_agent() - ``` - +```python Python +prefix_messages = [ + ChatMessage( + role="system", + content=( + "You are a Github Agent, and you can use tools to perform actions on Github." + ), + ) +] + +agent = FunctionCallingAgentWorker( + tools=tools, + llm=llm, + prefix_messages=prefix_messages, + max_function_calls=10, + allow_parallel_tool_calls=False, + verbose=True, +).as_agent() +``` +```typescript Typescript +coming soon +``` - -Converse with your LlamaIndex agent, and it will use the provoded tool(s) as necessary. + + - ```python Executing Agent - response = agent.chat("Hello! I would like to star a repo composiohq/composio on GitHub") - print("Response:", response) - ``` +```python Python +result = agent.chat("Star a repo composiohq/composio on GitHub") +``` +```typescript Typescript +coming soon +``` - -### Use Specific Apps - - - ```bash Filter Specific App - # To restrict agents from using all tools, filter specific tools - tools = composio_toolset.get_tools(apps=[App.GITHUB]) - ``` - - -### Use Specific Actions - - ```bash Filter Specific Action - # To restrict agents from using all the actions, filter specific actions - tools = composio_toolset.get_tools(actions=[Action.GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER]) - ``` - - diff --git a/docs/framework/media/langflow/1.jpg b/docs/framework/media/langflow/1.jpg new file mode 100644 index 00000000000..15c793d6beb Binary files /dev/null and b/docs/framework/media/langflow/1.jpg differ diff --git a/docs/framework/media/langflow/10.jpg b/docs/framework/media/langflow/10.jpg new file mode 100644 index 00000000000..a761146c53b Binary files /dev/null and b/docs/framework/media/langflow/10.jpg differ diff --git a/docs/framework/media/langflow/11.jpg b/docs/framework/media/langflow/11.jpg new file mode 100644 index 00000000000..39631c91111 Binary files /dev/null and b/docs/framework/media/langflow/11.jpg differ diff --git a/docs/framework/media/langflow/12.jpg b/docs/framework/media/langflow/12.jpg new file mode 100644 index 00000000000..87dd9165e64 Binary files /dev/null and b/docs/framework/media/langflow/12.jpg differ diff --git a/docs/framework/media/langflow/13.jpg b/docs/framework/media/langflow/13.jpg new file mode 100644 index 00000000000..30674473b20 Binary files /dev/null and b/docs/framework/media/langflow/13.jpg differ diff --git a/docs/framework/media/langflow/14.jpg b/docs/framework/media/langflow/14.jpg new file mode 100644 index 00000000000..e31a2da4f92 Binary files /dev/null and b/docs/framework/media/langflow/14.jpg differ diff --git a/docs/framework/media/langflow/2.jpg b/docs/framework/media/langflow/2.jpg new file mode 100644 index 00000000000..ebba5104abb Binary files /dev/null and b/docs/framework/media/langflow/2.jpg differ diff --git a/docs/framework/media/langflow/3.jpg b/docs/framework/media/langflow/3.jpg new file mode 100644 index 00000000000..2f74931d63b Binary files /dev/null and b/docs/framework/media/langflow/3.jpg differ diff --git a/docs/framework/media/langflow/4.jpg b/docs/framework/media/langflow/4.jpg new file mode 100644 index 00000000000..3d67ee8ac09 Binary files /dev/null and b/docs/framework/media/langflow/4.jpg differ diff --git a/docs/framework/media/langflow/5.jpg b/docs/framework/media/langflow/5.jpg new file mode 100644 index 00000000000..320baea667a Binary files /dev/null and b/docs/framework/media/langflow/5.jpg differ diff --git a/docs/framework/media/langflow/6.jpg b/docs/framework/media/langflow/6.jpg new file mode 100644 index 00000000000..7ffdccfcbf4 Binary files /dev/null and b/docs/framework/media/langflow/6.jpg differ diff --git a/docs/framework/media/langflow/7.jpg b/docs/framework/media/langflow/7.jpg new file mode 100644 index 00000000000..8aad781f06d Binary files /dev/null and b/docs/framework/media/langflow/7.jpg differ diff --git a/docs/framework/media/langflow/8.jpg b/docs/framework/media/langflow/8.jpg new file mode 100644 index 00000000000..5c7c5876213 Binary files /dev/null and b/docs/framework/media/langflow/8.jpg differ diff --git a/docs/framework/media/langflow/9.jpg b/docs/framework/media/langflow/9.jpg new file mode 100644 index 00000000000..49b41fd85b0 Binary files /dev/null and b/docs/framework/media/langflow/9.jpg differ diff --git a/docs/framework/openai.mdx b/docs/framework/openai.mdx index 636a59c8c29..86a07d78b9f 100644 --- a/docs/framework/openai.mdx +++ b/docs/framework/openai.mdx @@ -1,197 +1,138 @@ --- -title: "Using Composio With OpenAI" +title: "֎ Using Composio With OpenAI" sidebarTitle: "OpenAI" icon: "robot" -description: "Enable OpenAI assistants to seamlessly interact with external apps via Composio for enhanced functionality" +description: "Integrate Composio with OpenAI Assistants to let them seamlessly interact with external apps" --- -**Composio enables** your **OpenAI Assistants** to **connect** with many **tools**! +## Star A Repository on Github +In this example, we will use OpenAI Assistant to star a repository on Github using Composio Tools -### Install Packages & Connect a Tool - - - Goal: Enable OpenAI assistants to perform tasks like starring a repository on - GitHub via natural language commands - - -These steps prepare your environment to enable interactions between OpenAI and GitHub through Composio. - - - + + -```bash Connect your Github Account -pip install composio-openai - -# Connect your GitHub so agents can interact with it - -composio add github +```bash Python +pip install composio-openai openai ``` - - - - -```javascript Connect your Github Account -npm install openai -npm install composio-core -// Connect your GitHub so agents can interact with it - -composio add github +```javascript JavaScript +npm i composio-core openai ``` - - - - - - - - - ```python python - from openai import OpenAI - from composio_openai import ComposioToolSet, App - - openai_client = OpenAI() - # Initialise the Composio Tool Set - composio_toolset = ComposioToolSet() - ``` - - - + + - ```javascript javascript - import dotenv from 'dotenv'; - dotenv.config(); - - import { OpenAI } from "openai"; - import { OpenAIToolSet } from "composio-core"; +```python Python +from openai import OpenAI +from composio_openai import ComposioToolSet, Action - // Initializing the OpenAI client with the API key from environment variables - const openai_client = new OpenAI({ - apiKey: process.env.OPENAI_API_KEY - }); +openai_client = OpenAI() +composio_toolset = ComposioToolSet() +``` +```javascript JavaScript +import { OpenAIToolSet } from "composio-core"; +import OpenAI from "openai"; - // Initializing the Composio ToolSet with the API key from environment variables - const composio_toolset = new OpenAIToolSet({ - apiKey: process.env.COMPOSIO_API_KEY - }); - ``` +const toolset = new OpenAIToolSet(); +const openai = new OpenAI(); +``` - - - - - - - ```python python - # Get GitHub tools that are pre-configured - # Retrieve actions - actions = composio_toolset.get_tools(actions=[Action.GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER]) - ``` - - - + + +You can get all the tools for a given app as shown below, but you can get **specific actions** and filter actions using **usecase** & **tags**. Learn more [here](../../patterns/tools/use-tools/use-specific-actions) - ```javascript javascript - // Get GitHub tools that are pre-configured - // Retrieve actions - const tools = await composio_toolset.getTools({ - actions: ["github_start_repo"] - }); - ``` +```python Python +tools = composio_toolset.get_tools(apps=[App.GITHUB]) +``` +```javascript JavaScript +const tools = await toolset.getTools({ apps: ["github"] }); +``` - - + - - - + - ```python Execute an action using LL -my_task = "Star a repo composiohq/composio on GitHub" - -# Setup openai assistant - +```python Python assistant_instruction = "You are a super intelligent personal assistant" -# Prepare assistant - assistant = openai_client.beta.assistants.create( - name="Personal Assistant", - instructions=assistant_instruction, - model="gpt-4-turbo-preview", - tools=actions, # type: ignore + name="Personal Assistant", + instructions=assistant_instruction, + model="gpt-4-turbo-preview", + tools=tools, ) -# create a thread - thread = openai_client.beta.threads.create() +my_task = "Star a repo composiohq/composio on GitHub" message = openai_client.beta.threads.messages.create(thread_id=thread.id,role="user",content=my_task) -# Execute Agent with integrations - run = openai_client.beta.threads.runs.create(thread_id=thread.id,assistant_id=assistant.id) + +response_after_tool_calls = composio_toolset.wait_and_handle_assistant_tool_calls( + client=openai_client, + run=run, + thread=thread, +) +``` +```javascript JavaScript +async function createGithubAssistant(openai, tools) { + return await openai.beta.assistants.create({ + name: "Github Assistant", + instructions: "You're a GitHub Assistant, you can do operations on GitHub", + tools: tools, + model: "gpt-4o-mini" + }); +} ``` - - - - ```javascript javascript - const instruction = "Star a repo composiohq/composio on GitHub"; - - // Creating a chat completion request to the OpenAI model - const response = await openai_client.chat.completions.create({ - model: "gpt-4-turbo", - messages: [{ role: "user", content: instruction }], - tools: tools, - tool_choice: "auto", - }); - ``` - - - - - + - ```python python - - # Execute function calls - response_after_tool_calls = composio_toolset.wait_and_handle_assistant_tool_calls( - client=openai_client, - run=run, - thread=thread, - ) - - print(response_after_tool_calls) - ``` - ```javascript javascript - // Extracting tool calls from the response and logging them - var resp = response.choices[0].message.tool_calls - console.log(resp); - - // Handling the tool call using Composio ToolSet - await composio_toolset.handleToolCall(response); - ``` +```python Python +print(response_after_tool_calls) +``` +```javascript JavaScript +//With Streaming +async function executeAssistantTask(openai, toolset, assistant, task) { + const thread = await openai.beta.threads.create(); + const run = await openai.beta.threads.runs.create(thread.id, { + assistant_id: assistant.id, + instructions: task, + tools: tools, + model: "gpt-4o-mini", + stream: true + }); + + for await (const result of toolset.waitAndHandleAssistantStreamToolCalls(openai, run, thread)) { + console.log(result); + } +} + +// Without Streaming +async function executeAssistantTask(openai, toolset, assistant, task) { + const thread = await openai.beta.threads.create(); + const run = await openai.beta.threads.runs.create(thread.id, { + assistant_id: assistant.id, + instructions: task, + tools: tools, + model: "gpt-4o-mini", + stream: false + }); + const call = await toolset.waitAndHandleAssistantToolCalls(openai, run, thread); + console.log(call); +} + +(async() => { + const githubAssistant = await createGithubAssistant(openai, tools); + await executeAssistantTask( + openai, + toolset, + githubAssistant, + "Star the repository 'composiohq/composio'" + ); +})(); +``` - -### Use Specific Actions - - - ```bash Filter Specific Action - # To restrict agents from executing any actions, filter specific actions - actions = composio_toolset.get_tools(actions=[Action.GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER]) - ``` - - -### Use Specific Apps - - - ```bash Filter Specific App - # To restrict agents from using all tools, filter specific Apps - actions = composio_toolset.get_tools(apps=[App.GITHUB]) - ``` - diff --git a/docs/framework/phidata.mdx b/docs/framework/phidata.mdx index 7fa97d24448..d74f780b00c 100644 --- a/docs/framework/phidata.mdx +++ b/docs/framework/phidata.mdx @@ -1,97 +1,42 @@ --- -title: "Using Composio With phidata" +title: "Using Composio With Phidata" sidebarTitle: "Phidata" -icon: "robot" -description: "Integrate Composio with phidata agents to let them seamlessly interact with external apps" +icon: "link" +description: "Integrate Composio with Phidata agents to let them seamlessly interact with external apps" --- -**Composio enables** your **phidata assistants** to **connect** with many **tools**! - -### Install Packages & Connect a Tool - - - Goal: Star a repository on GitHub with natural language & phidata Assistant - - -These commands prepare your environment for seamless interaction between PhiData and Github. - - - ```bash Run Command -pip install composio-phidata - -#Connect your Github so agents can use it -composio add github - -#Check all supported apps -composio apps - ``` - +## Star A Repository on Github +In this example, we will use Phidata Agent to star a repository on Github using Composio Tools - - - - ```python Default Imports & Configuration -from composio_phidata import Action, ComposioToolSet - ``` - + +```bash Python +pip install composio-phidata +``` - - - ```python Tools For Github + +```python Python +from phi.assistant import Assistant +from composio_phidata import Action, ComposioToolSet + toolset = ComposioToolSet() -composio_tools = toolset.get_tools( - actions=[Action.GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER] -) - ``` - +``` - - - ```python PhiData Agent executes the task -from phi.assistant import Assistant + +You can get all the tools for a given app as shown below, but you can get **specific actions** and filter actions using **usecase** & **tags**. Learn more [here](../../patterns/tools/use-tools/use-specific-actions) +```python Python +composio_tools = toolset.get_tools(apps=[App.GITHUB]) +``` + + +```python Python assistant = Assistant(tools=composio_tools, show_tool_calls=True) - -assistant.print_response("Can you star composiohq/composio repo?") - ``` - - +``` - - - ```bash Executing Agents - -- Running: github_star_a_repository_for_the_authenticated_user(owner=composiohq, repo=composio) - I have successfully starred the repository `composiohq/composio` for you. - ``` - - - + +```python Python +assistant.print_response("Can you star composiohq/composio repo?") +``` - -### Use Specific Actions - - ```bash Filter Specific Action -# To restrict agents from using all the actions, filter specific actions -composio_toolset.get_tools(actions=[Action.GITHUB_CREATE_ISSUE]) - ``` - - -### Use Specific Apps - - - ```bash Filter Specific App -# To restrict agents from using all tools, filter specific tools -composio_toolset.get_tools(apps=[App.ASANA, App.GITHUB]) - ``` - - -### Filter apps actions by tags - - - ```bash Filter Actions by Tags -# To restrict agents from using all actions, filter the actions by tags -composio_toolset.get_tools(apps=[App.ASANA], tags=[Tag.ASANA_TASKS]) - ``` - + \ No newline at end of file diff --git a/docs/introduction/foundations/components/actions/action-guide.mdx b/docs/introduction/foundations/components/actions/action-guide.mdx deleted file mode 100644 index 523ce851b27..00000000000 --- a/docs/introduction/foundations/components/actions/action-guide.mdx +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: "πŸ› οΈ What can I do with Actions?" -sidebarTitle: "Actions" -icon: "wand-magic-sparkles" -description: "Understand more about Actions & Using Them" ---- - -### Introduction to Actions -Actions are **interfaces for interacting** with **external world** via - -1. **Tool API calls** (e.g., gmail API to send an email) -2. **System Code execution** (e.g., Python code to generate a report) - - -```python Python Fetching an Action -tools = tool_set.get_tools(actions=[Action.GITHUB_ACTIVITY_STAR_REPO_FOR_AUTHENTICATED_USER]) -``` - -```javascript JavaScript Fetching an Action -const tools = await composioToolset.getTools({ - actions: ["github_star_a_repository_for_the_authenticated_user"] -}); -``` - - - -Actions are function calling compatible which means they can be used via Agentic Frameworks or any other LLMs. - - -### Action Types - -1. **Actions to Manage External Tools**: These are actions that are pre-configured for specific tools like **Asana tool** has actions for creating tasks, adding comments, etc. -2. **Actions to Manage System**: Actions that **interact with the execution environment**, including **file systems, shell commands, and browser automation**. -3. **Custom Actions**: These are custom code actions that you write in Python, JavaScript. It can also **extend the capabilities of Composio to interact with any existing/new tools**. - -### Quick Starts - - - How to use Actions with Agentic Frameworks - - - How to use Actions without Agents - - - - How to create and use Custom Actions for existing & new tools - - - Filter actions on the basis of natural language - - - - -### Action Limits - - - Giving LLM's too many actions can lead to significant performance issues. - - ```python python - tools = tool_set.get_tools(apps=[App.ASANA]) - # Asana has 100+ actions - ``` - ```javascript javascript - const tools = toolset.getTools({ - apps: ["github"] - }) // Github has 100+ actions - ``` - - - -Empirical evidence indicates that agents perform optimally when limited to fewer than 20 actions. - -To optimize agent performance, it's essential to limit the number of actions available. This can be achieved through effective action filtering strategies. - -Here are some recommended approaches: -1. Use specific actions from a tool -2. Implement custom filtering logic - -By carefully curating the action set, you can significantly improve agent efficiency and response quality. diff --git a/docs/introduction/foundations/components/actions/processing.mdx b/docs/introduction/foundations/components/actions/processing.mdx deleted file mode 100644 index f7c3dc58e67..00000000000 --- a/docs/introduction/foundations/components/actions/processing.mdx +++ /dev/null @@ -1,83 +0,0 @@ ---- -title: "πŸ› οΈ Enhancing Action Inputs, Outputs & Schemas" -sidebarTitle: "Processing Actions" -icon: "wand-magic-sparkles" -description: "Master the art of preprocessing, postprocessing, and schema processing for optimal results." ---- - -## Refining Action Inputs, Outputs & Schemas - -In many scenarios, the raw inputs, outputs, or schemas of actions may benefit from additional processing. This refinement step can significantly improve the quality and usability of your data. Here are three key use cases: - -- **Preprocessing**: Generate or modify inputs dynamically at runtime, handling scenarios that may be challenging for the LLM to produce directly. -- **Postprocessing**: Streamline large action responses by filtering or formatting the data before it reaches the Language Model (LLM). -- **Schema Processing**: Modify the request schema to include additional fields or alter existing ones. - -Composio empowers you with the ability to define **custom Python functions** as preprocessors, postprocessors, or schema processors. - -These can be applied at two levels: - -1. **Tool-level**: Affects all actions within a specific tool. -2. **Action-level**: Tailored processing for individual actions. - -Here's how you can implement these processors: - - - -```python Define the Preprocessor, Postprocessor, and Schema Processor Functions -def tool_schema_processor(schema): - # Modify schema as needed - return modified_schema - -def tool_preprocessor(input_data): - # Modify input_data as needed - return modified_input_data - -def tool_postprocessor(output_data): - # Process output_data as needed - return processed_output_data - -def action_schema_processor(schema): - # Modify schema as needed - return modified_schema - -def action_preprocessor(input_data): - # Modify input_data as needed - return modified_input_data - -def action_postprocessor(output_data): - # Process output_data as needed - return processed_output_data -``` - - - - -```python Set the schema, pre, and post processors while creating the toolset -# While defining the toolset, you can define the schema, pre, and post processors -composio_toolset = ComposioToolSet( - processors={ - "schema": { - App.GITHUB: tool_schema_processor, - Action.GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER: action_schema_processor, - }, - "pre": { - App.GITHUB: tool_preprocessor, - Action.GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER: action_preprocessor, - }, - "post": { - App.GITHUB: tool_postprocessor, - Action.GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER: action_postprocessor, - }, - }, -) - -tools = composio_toolset.get_tools(apps=[App.GITHUB]) -``` - - - - - - Ensure that your schema processing, preprocessing, and postprocessing functions are efficient and don't introduce significant latency. - diff --git a/docs/introduction/foundations/components/custom_actions.mdx b/docs/introduction/foundations/components/custom_actions.mdx deleted file mode 100644 index 6c066baa319..00000000000 --- a/docs/introduction/foundations/components/custom_actions.mdx +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: "Creating a Custom Action" -sidebarTitle: "Custom Actions" -icon: "gear" -description: "Complete customisation by creating your own actions" ---- - -## Overview - -**Custom Actions** in Composio allow users to execute actions locally, enhancing privacy and customization. - -Composio supports two action types: - -1. **Composio-Managed Actions:** Available on the [dashboard](https://app.composio.dev/). -2. **Custom Actions:** Defined and executed locally or in the tool [workspace](/introduction/foundations/components/workspace). - -**Custom actions** can be defined for **existing tools (gmail, google_calendar, etc.) or for your own tools.** - -```python Python Defining Custom Action -from composio import action - -@action(toolname="cow", requires=["cowsay"]) -def say(message: str) -> str: - """ - Cow will say whatever you want it to say. - - :param message: Message string - :return greeting: Formatted message. - """ - # A Description needs to be added to each Custom Action function - # The format is: - # """ - # description line - # :param input_param_1: input_param_description - # :param input_param_2: input_param_2_description - # :return output_variable: output_variable_description - # """ - import cowsay - - return cowsay.get_output_string("cow", message) -``` -```javascript Javascript Defining Custom Action -import { z } from "zod"; -import { ComposioToolSet } from "composio-core"; - -const toolset = new ComposioToolSet({}); - -(async () => { - await toolset.createAction({ - actionName: "sayHello", - toolName: "greetings", - description: "A simple action that says hello to someone", - inputParams: z.object({ - name: z.string().describe("Name of the person to greet") - }), - callback: async (inputParams) => { - return { - message: `Hello ${inputParams.name}!` - }; - } - }); - - const result = await toolset.executeAction("sayHello", { name: "World" }); - console.log("Action result:", result); // Will print: { message: "Hello World!" } -})(); -``` - -In this example, we **create a custom tool called "cow"** that uses the **`cowsay` library** to **output a message**. - -### Quick Starts - - - Learn more about creating a custom action for existing tools (gmail, google_calendar, etc.) & using it in your agent - diff --git a/docs/introduction/foundations/components/entity/entity-guide.mdx b/docs/introduction/foundations/components/entity/entity-guide.mdx deleted file mode 100644 index ec2c8a28326..00000000000 --- a/docs/introduction/foundations/components/entity/entity-guide.mdx +++ /dev/null @@ -1,471 +0,0 @@ ---- -title: "πŸ§‘β€πŸ€β€πŸ§‘ Authentication" -sidebarTitle: "Authentication" -icon: "users" -description: "Manage all the connected accounts of your Users" ---- - -## Introduction to Entities - -- **Each unique user** is represented by a **unique entity id**. -- If you have **two users, Jessica and Melissa**, they will have **unique entity ids**. - -## Introduction to Connected Accounts -- When a user connects their account, a `connected_account` object is created. -- This object securely stores **authentication data** such as **access tokens and refresh tokens**. - -### πŸ” Master Authentication in Minutes! - - - Unlock the full potential of Composio's secure authentication system - Perfect for both beginners and advanced users. - - -### Connecting an Account for your User - -Connecting a user account requires a few API calls to authenticate and authorize access. The process involves: - -1. **Fetch Required Parameters** - Get the authentication requirements for the chosen application -2. **Collect User Input** - Gather the required parameters from your user interface -3. **Create Connection** - Initialize a new connection with the collected parameters -4. **Handle OAuth Flow** - For OAuth applications, redirect the user to complete authorization -5. **Verify Status** - Check that the connection was successful - -The code snippets below demonstrate how to implement this flow in your application. - - - -To create a connected account for your user: - -1. Fetch required auth parameters for the application -2. Collect these parameters from the user -3. Initiate a new connection request - - Linear: Requires `api_key` - - -```python Python - Fetch Auth Parameters -from composio import ComposioToolSet, App -toolset = ComposioToolSet() - -response = toolset.get_expected_params_for_user(app=App.LINEAR) # can use integration_id instead of app - -print(response["expected_params"]) -``` - -```javascript Javascript - Fetch Auth Parameters -import { Composio, OpenAIToolSet } from "composio-core"; - -const toolset = new OpenAIToolSet(); - -const expectedInputFields = await toolset.getExpectedParamsForUser({ - app: "gmail", -}); - -console.log(expectedInputFields) -``` - - -Collect the required parameters from your user through your preferred interface (UI, chat, or API). - - -All parameters should be provided as strings. - - - - - - -In the code snippets below replace `redirect_url` - - -```python Python - New Connection - -# This is the URL that the user will be redirected to after completing the authentication process -redirect_url = "https://yourwebsite.com/connection/callback" - -entity_id = "Jessica" # This is the unique identifier for the user - -# Collect the parameters from the user -# Here we are assuming that the user has provided the parameters -# In a real-world scenario, you would collect these parameters from the user via your app's UI. -collected_params = { - # "api_key": "1234567890" # This is an example, actual values will be different -} - -# Initiate the connection -connection_request = toolset.initiate_connection(connected_account_params=collected_params,entity_id=entity_id,app=App.LINEAR,redirect_url=redirect_url) - -# If the connection method is OAuth, redirect the user to the URL below -print(connection_request.redirectUrl) - -# Check the status of the connection -print(connection_request.status) -``` - -```javascript Javascript - New Connection -const redirectUrl = "https://yourwebsite.com/connection/callback" - -const entityId = "Jessica" //This is the unique identifier for the user - -// Collect the parameters from the user -// Here we are assuming that the user has provided the parameters -// In a real-world scenario, you would collect these parameters from the user via your app's UI. -const collectedParams = { - // "api_key": "1234567890" // This is an example, actual values will be different -} - -const connectionRequest = await toolset.client.connectedAccounts.initiate({ - data: { - ...collectedParams - }, - userUuid: entityId, - integrationId: expectedInputFields.integrationId, - redirectUri: redirectUrl -}); - -console.log("Click on this link to connect your account", connectionRequest.redirectUrl) - -const connectedAccount = await connectionRequest.waitUntilActive(30); // Wait for the connection to be active - -console.log("Connected account is active", connectedAccount) -``` - - - -Some applications require user redirection to complete the authentication process. -Gmail for example requires redirecting the user to Google's login page. - - - - - -If you want to use connection params locally and build custom actions - - - -Connection status can be `failed`, `initiated` or `active`. - - -```python Python - Fetch the connection status & details (Optional) -connected_account = toolset.get_connected_account(connection_request.connectedAccountId) - -# Get the parameters for your local usage -print(toolset.get_auth_params(connection_id=connected_account.id)) - -#print(connected_account.connectionParams) # use this for raw/advanced cases -``` - -```javascript Javascript - Fetch the connection params (Optional) -const connectedAccount = await toolset.client.connectedAccounts.get({ - connectedAccountId: connectionRequest.connectedAccountId -}) - -const connectedAccountAuthParams = await toolset.getAuthParams({ - connectedAccountId: connectedAccount.connectedAccountId -}) - -console.log("Connected account auth params", connectedAccountAuthParams) - -//console.log("Connected account raw auth params", connectedAccount.connectionParams) - -``` - - -Example of how connection params would look like - - -``` JSON Auth Params Output -{ - "base_url": "", // This is the base URL for the API Ex. https://api.linear.app - "params": [{ // This is the list of all the params - "name": "x-api-key", - "in": "header", // `in` value could be of type `header`, `query` - "value": "" - }], - "body": {} -} -``` -``` Javascript Raw Auth Params Output -Connected account raw auth params { - scope: '********', - scopes: '********', - id_token: '********', - client_id: '********', - expires_in: '********', - token_type: '********', - redirectUrl: 'https://accounts.google.com/o/oauth2/v2/auth?client_id=96-8p515bt7ijf94c2bf4a5lev5jr6r7oc1.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fbackend.composio.dev%2Fapi%2Fv1%2Fauth-apps%2Fadd&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgmail.modify&response_type=code&access_type=offline&prompt=consent&state=staging_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.30.W9PV-ncrbbPhnjfcgBCN8ZNn9A8V2lzCbXQR2fOXht4&code_challenge=YpyY74p3BJU_-a_mIq4GZyka2FlpnH4APVIfQ&code_challenge_method=S256', - callback_url: '********', - client_secret: '********', - code_verifier: '********', - refresh_token: '********', - headers: { - Authorization: 'Bearer ya29.-BhZtwh0ZLk-', - }, - queryParams: {}, - base_url: 'https://www.googleapis.com' -} -``` - - - - - - -You can fetch connection details after user is redirected back to your app. (If redirect was needed) - -`connection_status` & `connectedAccountId` will be available in the query params. - - - - -### Get All Connected accounts - - - -```python Get All Connected Account -entity = toolset.get_entity(id="Jessica") #filter based on entity id -try: - connected_accounts = entity.get_connections() #lists all connections of the entity - entity.get_connection(app=App.GITHUB) #filters based on app name - entity.get_connection(connected_account_id="9") #filters based on connected account id for an entity - print(connected_accounts) -except NoItemsFound as e: - print("No connected account found") -``` - - - - - -```javascript Get All Connected Account -const tool_set = new OpenAIToolSet({ - apiKey: process.env.OPENAIKEY, - entityId: "Jessica" -}); -//filters based on connected account id for an entity -console.log(await tool_set.connectedAccounts.get({connectedAccountId:'9'})) -//filters connections based on appName for an entity -console.log(tool_set.client.integrations.get({ - appName:'linear' -})) -//list all connections based on entityId -console.log(await tool_set.connectedAccounts.list()) -``` - - - - - -Returns a list of Connections for an integration - -```curl cURL -curl --request GET \ - --url https://backend.composio.dev/api/v1/connectedAccounts \ - --header 'X-API-Key: ' -``` - - -Returns Connections for a Connected Account ID -```curl cURL -curl --request GET \ - --url https://backend.composio.dev/api/v1/connectedAccounts/{connectedAccountId} \ - --header 'X-API-Key: ' -``` - - - - -Here’s your modified documentation with three tabs (Python, JavaScript, and API), each containing relevant steps and code snippets: - -## Execute Agent and Perform Tasks on Behalf of an Entity - - - - - ```python Python - # Step 1: Fetch Available Actions from GitHub - - from composio_openai import ComposioToolSet, App - from openai import OpenAI - - openai_client = OpenAI() - - # Entity ID can be configured based on the user, here it is "Jessica" - tool_set = ComposioToolSet(entity_id="Jessica") - - # Fetch actions for GitHub - actions = tool_set.get_tools(apps=[App.GITHUB]) - - - # Step 2: Execute Agent Task on GitHub - - my_task = "Star a repo composiohq/composio on GitHub" - - # Setup OpenAI assistant - assistant_instruction = "You are a super intelligent personal assistant" - - assistant = openai_client.beta.assistants.create( - name="Personal Assistant", - instructions=assistant_instruction, - model="gpt-4-turbo-preview", - tools=actions # fetched tools - ) - - # Create a conversation thread - thread = openai_client.beta.threads.create() - message = openai_client.beta.threads.messages.create( - thread_id=thread.id, - role="user", - content=my_task - ) - - # Execute the Agent with the integrations - run = openai_client.beta.threads.runs.create( - thread_id=thread.id, - assistant_id=assistant.id - ) - - # Wait for and handle tool calls from the assistant - response_after_tool_calls = tool_set.wait_and_handle_assistant_tool_calls( - client=openai_client, - run=run, - thread=thread, - ) - - print(response_after_tool_calls) - ``` - - - - - - - ```javascript JavaScript - // Step 1: Fetch Available Actions from GitHub - - import { OpenAIToolSet } from "composio-core"; - import { OpenAI } from "openai"; - - const llm = new OpenAI({ - apiKey: process.env.OPENAI_API_KEY, - }); - const toolset = new OpenAIToolSet({ - apiKey: process.env.COMPOSIO_API_KEY, - entityId: "Jessica", - }); - - // Fetch actions for GitHub - const tools = await toolset.getTools({ apps: ["github"] }); - - // Step 2: Execute Agent Task on GitHub - - const task = "Star a repo composiohq/composio on GitHub"; - const repo = "composio"; - const owner = "composiohq"; - - // Create a thread and instruct assistant - const assistantThread = await llm.beta.threads.create({ - messages: [ - { - role: "assistant", - content: "You are an assistant tasked with starring a repository on GitHub.", - }, - ], - }); - - // Setup the assistant with tools - const assistant = await llm.beta.assistants.create({ - name: "SWE agent", - instructions: `Your goal is to star the repository: ${owner}/${repo}`, - model: "gpt-4-turbo", - tools: tools, - }); - - // Send user task to the thread - await llm.beta.threads.messages.create(assistantThread.id, { - role: "user", - content: task, - }); - - // Execute and poll for tool calls - const stream = await llm.beta.threads.runs.createAndPoll(assistantThread.id, { - assistant_id: assistant.id, - instructions: `Repo is: ${repo} and your goal is to ${task}`, - tool_choice: "required", - }); - - // Handle tool calls - await toolset.waitAndHandleAssistantToolCalls(llm, stream, assistantThread, "default"); - ``` - - - - - - - - - - ```curl API - - curl --request GET \ - --url https://backend.composio.dev/api/v2/actions \ - --header 'X-API-Key: ' - ``` - - - - - - ```curl API - - curl --request POST \ - --url https://backend.composio.dev/api/v2/actions/GITHUB_STAR_A_REPO/execute \ - --header 'Content-Type: application/json' \ - --header 'X-API-Key: ' \ - --data '{ - "entityId": "Jessica", - "input": { - "repo": "composio", - "owner": "composiohq" - } - }' - - - # Optionally, you can retrieve the action details before execution - curl --request GET \ - --url https://backend.composio.dev/api/v1/actions/GITHUB_ACTIVITY_STAR_REPO_FOR_AUTHENTICATED_USER \ - --header 'X-API-Key: ' - ``` - - - - - - -### Examples of Authentication Flows - - - Learn how to implement OAuth authentication in your application - - - - Learn how to implement API Key authentication in your application - \ No newline at end of file diff --git a/docs/introduction/foundations/components/integrations/integration-guide.mdx b/docs/introduction/foundations/components/integrations/integration-guide.mdx deleted file mode 100644 index cc97af7f0cd..00000000000 --- a/docs/introduction/foundations/components/integrations/integration-guide.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: "Integrations" -sidebarTitle: "Integrations" -icon: "plug" -description: "Allow your users to connect with any Apps." ---- - -## Overview of Integrations - -Integrations in Composio are configuration objects that define how your application connects to external services and APIs. Each integration encapsulates the authentication details, permissions, and API specifications needed to establish secure connections with services like GitHub, Slack, or HubSpot. - - - Integrations include critical configuration like OAuth credentials (Client ID/Secret), required permissions scopes, and API endpoint specifications that determine how your users can interact with the external service. - - -For example: -- When you create a GitHub integration, you specify OAuth authentication parameters and permission scopes like "repo:read" -- This integration then serves as a reusable template - any user connecting their GitHub account through this integration will have the same standardized access level and authentication flow -- This ensures consistent and secure access patterns across your entire user base - -So ideally you will only build **one integration per tool or application** and **allow all your users to connect using it**. -
- - - Discover how to create and manage powerful integrations in Composio - diff --git a/docs/introduction/foundations/components/triggers/trigger-guide.mdx b/docs/introduction/foundations/components/triggers/trigger-guide.mdx deleted file mode 100644 index 3a0e2809545..00000000000 --- a/docs/introduction/foundations/components/triggers/trigger-guide.mdx +++ /dev/null @@ -1,189 +0,0 @@ ---- -title: "πŸ› οΈ Getting Started with Triggers" -sidebarTitle: "Triggers" -icon: "webhook" -description: "How to enable triggers & listen to them?" ---- - -## Using Triggers - -**Prerequisite**: Successfully **linking an account** & then having `connectedAccountId`. - -Triggers are predefined conditions that, when met, initiate webhooks to your agents. -These webhooks usually contain payloads which can be used to our advantage. - -* **Github Commit Event**: Triggers a webhook whenever there is a new commit made to a particular repository. -* **New email in inbox (Gmail)**: Triggers a webhook whenever a new email has been received. - -## Enabling Triggers - - - - -```Bash Enable Trigger from CLI -# In CLI -composio triggers enable -# trigger_name is the name of the trigger - slackbot_receive_thread_reply - -## To disable a trigger -composio triggers disable -``` - - - - -```python Enable Trigger using python code -from composio import ComposioToolSet, Action, App - -tool_set = ComposioToolSet() -entity = tool_set.get_entity() - -# config is optional, it can be used to pass additional parameters for the trigger -entity.enable_trigger( - app=App.GITHUB, trigger_name="GITHUB_PULL_REQUEST_EVENT", config={"owner": "composiohq", "repo": "composio"} -) # Enable trigger - -# entity.disable_trigger("") # Disable trigger via ID -``` - - - - - -```javascript Enable Trigger using javascript code -import { OpenAIToolSet } from "composio-core"; - -const toolset = new OpenAIToolSet({}); -const entity = toolset.client.getEntity("default"); - -(async () => { - // config is optional, it can be used to pass additional parameters for the trigger - console.log( - "Setting up trigger for", - await entity.setupTrigger("github", "GITHUB_PULL_REQUEST_EVENT", { - owner: "composiohq", - repo: "composio", - }) - ); // Enable trigger -})(); - -//await entity.disableTrigger("") -``` - - - -When you Initiate a Connection, you receive the connectionAccountID - -```API curl via curl command -curl --request POST \ - --url https://backend.composio.dev/api/v1/triggers/enable/{connectedAccountId}/GITHUB_PULL_REQUEST_EVENT \ - --header 'Content-Type: application/json' \ - --header 'X-API-Key: ' \ - --data '{ - "triggerConfig": { - "owner":"composiohq", - "repo":"composio" - } -}' -``` - - - -
- 1. Login at [Composio's Website](https://app.composio.dev) 2. Go to the Tools section 3. Click on any app you want to integrate 4. Click on Setup on [App Name] Integration 5. Choose your integration name and click Save -6. Then Click on "Connect to [App Name]" and Authenticate with your Account -7. Congratulations! Integration was successful! + + +You can create an integration using the SDK by following the steps below: + + + +```python Python +from composio import ComposioToolSet + +toolset = ComposioToolSet() +entity = toolset.get_entity("Jessica") +``` +```javascript JavaScript +import { Composio } from "composio-core"; -### Fetching all Integrations +const toolset = new Composio(); +const entity = toolset.getEntity("Jessica"); +``` + + + +You need to provide the following parameters to create an integration: +- `name`: Name of the integration +- `app_id`: App ID of the integration, you can find it [here](https://docs.composio.dev/api-reference/apps/get-app) +- `auth_mode`: Authentication mode of the integration (e.g., OAUTH2, OAUTH1, API_KEY, BASIC, BEARER_TOKEN) +- `use_composio_auth`: You can use the OAuth flow provided by Composio by setting this to `True` or use your own ClientID and ClientSecret by setting this to `False` & providing the fields as shown below + +```python Python +# Using Composio's default OAuth flow +integration = entity.client.integrations.create( + name="GITHUB_Integration_Demo", + app_id="01e22f33-dc3f-46ae-b58d-050e4d2d1909", + auth_mode="OAUTH2", + use_composio_auth=True +) + +# Using your own OAuth flow +integration = entity.client.integrations.create( + name="GITHUB_Integration_Demo", + app_id="01e22f33-dc3f-46ae-b58d-050e4d2d1909", + auth_mode="OAUTH2", + use_composio_auth=False, + auth_config={ + "client_id": "", + "client_secret": "" + } +) + +``` +```javascript JavaScript +// Using Composio's default OAuth flow +const integration = await entity.integrations.create({ + name: "GITHUB_Integration_Demo", + appId: "01e22f33-dc3f-46ae-b58d-050e4d2d1909", + authScheme: "OAUTH2", + useComposioAuth: true, +}); + +// Using your own OAuth flow +const integration = await entity.integrations.create({ + name: "GITHUB_Integration_Demo", + appId: "01e22f33-dc3f-46ae-b58d-050e4d2d1909", + authScheme: "OAUTH2", + useComposioAuth: false, + authConfig: { + client_id: "", + client_secret: "" + } +}); +``` + + + +Since the created integration uses OAuth, you need to redirect the user to the URL returned by the `redirectUrl` field in the response. +You can initiate a connection using the integration by following the steps below: + +```python Python +request = entity.initiate_connection("GITHUB", redirect_url="https://yourwebsite.com/connection/success", integration=integration) +print(request.redirectUrl) +``` +```javascript JavaScript +const request = await entity.initiateConnection({ + appName: "github", + redirectUrl: "https://composio.dev", + integrationId: integration.id +}); +console.log(request.redirectUrl) +``` + + + + + + +### How to Fetch Integrations ```python Python from composio import ComposioToolSet, App toolset = ComposioToolSet() -print(toolset.get_integrations()) # get all integrations -print(toolset.get_integrations(app=App.GMAIL)) #filter based on app -print(toolset.get_integration(id="ADD THE ID HERE")) #filter based on integration id +# get all integrations +print(toolset.get_integrations()) + +#filter based on app +print(toolset.get_integrations(app=App.GMAIL)) + +#filter based on integration id +print(toolset.get_integration(id="")) # By auth scheme print(toolset.get_integrations(auth_scheme="BEARER_TOKEN")) @@ -51,44 +151,68 @@ print(toolset.get_integrations(auth_scheme="BEARER_TOKEN")) ```javascript JavaScript import { OpenAIToolSet } from "composio-core"; +const openai_client = new OpenAIToolSet(); -const openai_client = new OpenAIToolSet({ - apiKey: process.env.OPENAIKEY -}); +// //get all integrations +console.log(openai_client.client.integrations.list()) + +// //filter based on app +console.log(openai_client.client.integrations.get({ appName:'gmail'})) -console.log(openai_client.client.integrations.list()) //lists all integrations -console.log(openai_client.client.integrations.get({ - appName:'gmail' -})) //filter based on app name -console.log(await openai_client.client.integrations.get({integrationId:"ADD THE ID HERE"})) //filter based on integration id +// //filter based on integration id +console.log(await openai_client.client.integrations.get({integrationId:""})) ``` ### Creating a new connection using an Integration -You can follow the same steps as mentioned in [Creating a new connection](/patterns/Auth/connected_account) and use integration object. +You can follow the same steps as mentioned in [Creating a new connection](/patterns/Auth/connected_account) and use integration object (Python) or integrationId (JavaScript). ```python Python from composio import ComposioToolSet -toolset = ComposioToolSet(api_key=os.getenv("COMPOSIO_API_KEY"), entity_id="Jessica") +toolset = ComposioToolSet(entity_id="Jessica") entity = toolset.get_entity() integration = entity.client.integrations.get_by_id("integration_id...") -connection_request = entity.initiate_connection(app_name="TWITTER", redirect_url="redirect_url...", integration=integration) +connection_request = entity.initiate_connection( + app_name="TWITTER", + redirect_url="https://yourwebsite.com/connection/success", + integration=integration, +) # If the connection method is OAuth, redirect the user to the URL below print(connection_request.redirectUrl) ``` + +```javascript JavaScript +import { OpenAIToolSet } from "composio-core"; + +const toolset = new OpenAIToolSet(); + +const connectionRequest = await toolset.client.connectedAccounts.initiate({ + appName: "gmail", + redirect_url: "https://yourwebsite.com/connection/success", + integrationId: integration.id, + entityId:"Jessica" +}); + +console.log(connectionRequest.redirectUrl); +``` -### Whitelabeling the OAuth Developer App Using Integrations +### Using Your Own OAuth Developer App -Integrations can be used to customise the OAuth Developer App that is shown to the user when initiating a connection. +When creating an integration, you can use your own OAuth Developer App instead of Composio's default one, you can follow the same steps as mentioned in [Creating a New Integration](#creating-a-new-integration) and: -Create an Integration and toggle on "Use your own Developer App" +1. Enable the toggle "Use your own Developer App" +2. Enter your OAuth credentials: + - Client ID + - Client Secret -Enter your ClientID and ClientSecret and save the integration. + +When users connect using this integration, they'll see your app's name and logo in the OAuth consent screen instead of Composio's. Checkout the live demo [here](https://whitelabel-eight.vercel.app/) + -Now you can use this integration and the user in auth flow should see the custom developer app. \ No newline at end of file + \ No newline at end of file diff --git a/docs/patterns/Auth/connected_account.mdx b/docs/patterns/Auth/connected_account.mdx index 5b56eebc0b0..b0a5602d03d 100644 --- a/docs/patterns/Auth/connected_account.mdx +++ b/docs/patterns/Auth/connected_account.mdx @@ -1,260 +1,167 @@ --- -title: "Connected Accounts" +title: "Create & Manage Connections for Users" sidebarTitle: "Connections" icon: "link" -description: "Guide to creating connections for multiple users" +description: "Learn how to securely manage and authenticate multiple user connections" --- -### Introduction to Connected Accounts -- When a user connects their account, a `connected_account` object is created. -- **Connected Account** securely stores **authentication data** such as **api keys, access tokens and refresh tokens**. - -### Introduction to Entities - -- **Each unique user/tenant** is represented by a **unique entity id**. -- If you have **two users, Jessica and Melissa**, they will each have **unique entity ids**. - -### Connecting an Account for your User - -Connecting a user account requires a few API calls to authenticate and authorize access. The process involves: +### Entities -1. **Fetching Parameters to create a Connection** - Get the authentication requirements for the chosen application (API Key, Subdomain URL, Username etc.) -2. **Collecting those parameters from the user** - Gather the required parameters from your user interface -3. **Creating a Connection** - Initialize a new connection with the collected parameters -4. **Handling OAuth Flow** - For OAuth applications, redirect the user to complete authorization -5. **Verifying Connection Status** - Check that the connection was successful +- Each **user** is represented by a **unique entity ID**. +- If you have two users, **Jessica** and **Melissa**, they will each have **unique entity IDs**. +If not specified, `default` will be used as the entity ID. -### Code Snippets for Connecting an Account - - -To create a connected account for your user: - -1. Fetch required auth parameters for the application -2. Collect these parameters from the user -3. Initiate a new connection request - - Linear: Requires `api_key`, Shopify: Requires `shop_name` for OAuth flow +You can use an entity object to manage connected accounts and perform actions on behalf of a user (more on this [here](/patterns/tools/use-tools/action-guide-without-agents#how-can-i-use-tools-for-a-specific-user)). Here's how to retrieve an entity object: -```python Python - Fetch Auth Parameters -from composio import ComposioToolSet, App -toolset = ComposioToolSet() +```python Python +from composio import ComposioToolSet -response = toolset.get_expected_params_for_user(app=App.LINEAR) # can use integration_id instead of app - -print(response["expected_params"]) +toolset = ComposioToolSet() +entity = toolset.get_entity(id='Jessica') ``` -```javascript Javascript - Fetch Auth Parameters -import { Composio, OpenAIToolSet } from "composio-core"; +```javascript JavaScript +import { OpenAIToolSet } from "composio-core"; const toolset = new OpenAIToolSet(); - -const expectedInputFields = await toolset.getExpectedParamsForUser({ - app: "gmail", -}); - -console.log(expectedInputFields) +const entity = toolset.client.getEntity(id='Jessica'); ``` -Collect the required parameters from your user through your preferred interface (UI, chat, or API). - - -All parameters should be provided as strings. - - - - - +### Connected Accounts +- When a user connects their account, a `connected_account` object is created. +- **Connected Account** securely stores **authentication data** such as **API keys, access tokens and refresh tokens**. -In the code snippets below replace `redirect_url` +### How to initiate a new connection for your user +Follow these steps to initiate a new connection for your user (for both OAuth and non-OAuth based Apps): + + +Initiate a new connection by passing the redirect url, entity id & app. -```python Python - New Connection - -# This is the URL that the user will be redirected to after completing the authentication process -redirect_url = "https://yourwebsite.com/connection/callback" +```python Python +from composio import ComposioToolSet, App +toolset = ComposioToolSet() -entity_id = "Jessica" # This is the unique identifier for the user +# URL that the user will be redirected to after completing the authentication process +redirect_url = "https://yourwebsite.com/connection/success" -# Collect the parameters from the user -# Here we are assuming that the user has provided the parameters -# In a real-world scenario, you would collect these parameters from the user via your app's UI. -collected_params = { - # "api_key": "1234567890" # This is an example, actual values will be different -} +# Unique identifier for the user for whom the connection is being created +entity_id = "Jessica" -# Initiate the connection -connection_request = toolset.initiate_connection(connected_account_params=collected_params,entity_id=entity_id,app=App.LINEAR,redirect_url=redirect_url) +# Initiate new connection (You can use integration_id instead of app) +connection_request = toolset.initiate_connection(redirect_url=redirect_url, entity_id=entity_id, app=App.GMAIL) -# If the connection method is OAuth, redirect the user to the URL below +# Redirect the user to the URL below print(connection_request.redirectUrl) -# Check the status of the connection +# Check the status of the connection (it can be initiated, active, or failed) print(connection_request.connectionStatus) ``` -```javascript Javascript - New Connection -const redirectUrl = "https://yourwebsite.com/connection/callback" +```javascript Javascript +import { OpenAIToolSet } from "composio-core"; +const toolset = new OpenAIToolSet(); -const entityId = "Jessica" # This is the unique identifier for the user +// URL that the user will be redirected to after completing the authentication process +const redirectURL = "https://yourwebsite.com/connection/success" -// Collect the parameters from the user -// Here we are assuming that the user has provided the parameters -// In a real-world scenario, you would collect these parameters from the user via your app's UI. -const collectedParams = { - // "api_key": "1234567890" // This is an example, actual values will be different -} +// Unique identifier for the user for whom the connection is being created +const entityId = "Jessica" +// Initiate new connection (You can use integration_id instead of app) const connectionRequest = await toolset.client.connectedAccounts.initiate({ - data: { - ...collectedParams - }, - userUuid: entityId, - integrationId: expectedInputFields.integrationId, - redirectUri: redirectUrl + appName: "gmail", + redirect_url: redirectURL, + entityId: entityId, + authMode: "OAUTH2", + authConfig: {}, }); -console.log("Click on this link to connect your account", connectionRequest.redirectUrl) - -const connectedAccount = await connectionRequest.waitUntilActive(30); // Wait for the connection to be active +// Redirect the user to the URL below +console.log(connectionRequest.redirectUrl); -console.log("Connected account is active", connectedAccount) +// Check the status of the connection (it can be initiated, active, or failed) +console.log(connectionRequest.connectionStatus); ``` - - -Some applications require user redirection to complete the authentication process. -Gmail for example requires redirecting the user to Google's login page. - - - - - - - - - ```python Get All Connected Account - entity = toolset.get_entity(id="Jessica") #filter based on entity id - try: - connected_accounts = entity.get_connections() #lists all connections of the entity - entity.get_connection(app=App.GITHUB) #filters based on app name - entity.get_connection(connected_account_id="9") #filters based on connected account id for an entity - print(connected_accounts) - except NoItemsFound as e: - print("No connected account found") - ``` - - - - - ```javascript Get All Connected Account - const tool_set = new OpenAIToolSet({ - apiKey: process.env.OPENAIKEY - }); - //filters based on connected account id for an entity - console.log(await tool_set.connectedAccounts.get({connectedAccountId:'9'})) - //filters connections based on appName for an entity - console.log(tool_set.client.integrations.get({ - appName:'linear' - })) - //list all connections based on entityId - console.log(await tool_set.connectedAccounts.list()) - ``` - - +Each App integration has a unique **integration ID**. You can use this ID instead of the **app name** when creating connections. - - - - - -If you want to use connection params locally and build custom actions - - - -Connection status can be `failed`, `initiated` or `active`. - + +Get the expected parameters required to create a connection & pass then while initiating a new connection (API Key, Subdomain URL, Username etc.). + + -```python Python - Fetch the connection status & details (Optional) -connected_account = toolset.get_connected_account(connection_request.connectedAccountId) +```python Python +from composio import ComposioToolSet, App +toolset = ComposioToolSet() -# Get the parameters for your local usage -print(toolset.get_auth_params(connection_id=connected_account.id)) +# You can use integration_id instead of app +response = toolset.get_expected_params_for_user(app=App.FIRECRAWL) -#print(connected_account.connectionParams) # use this for raw/advanced cases +print(response["expected_params"]) ``` -```javascript Javascript - Fetch the connection params (Optional) -const connectedAccount = await toolset.client.connectedAccounts.get({ - connectedAccountId: connectionRequest.connectedAccountId -}) - -const connectedAccountAuthParams = await toolset.getAuthParams({ - connectedAccountId: connectedAccount.connectedAccountId -}) - -console.log("Connected account auth params", connectedAccountAuthParams) +```javascript Javascript +import { OpenAIToolSet } from "composio-core"; +const toolset = new OpenAIToolSet(); -//console.log("Connected account raw auth params", connectedAccount.connectionParams) +// You can use integration_id instead of app +const expectedInputFields = await toolset.getExpectedParamsForUser({ + app: "firecrawl", +}); +console.log(expectedInputFields) ``` + -Example of how connection params would look like - + -``` JSON Auth Params Output -{ - "base_url": "", // This is the base URL for the API Ex. https://api.linear.app - "params": [{ // This is the list of all the params - "name": "x-api-key", - "in": "header", // `in` value could be of type `header`, `query` - "value": "" - }], - "body": {} -} -``` -``` Javascript Raw Auth Params Output -Connected account raw auth params { - scope: '********', - scopes: '********', - id_token: '********', - client_id: '********', - expires_in: '********', - token_type: '********', - redirectUrl: 'https://accounts.google.com/o/oauth2/v2/auth?client_id=96-8p515bt7ijf94c2bf4a5lev5jr6r7oc1.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fbackend.composio.dev%2Fapi%2Fv1%2Fauth-apps%2Fadd&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgmail.modify&response_type=code&access_type=offline&prompt=consent&state=staging_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.30.W9PV-ncrbbPhnjfcgBCN8ZNn9A8V2lzCbXQR2fOXht4&code_challenge=YpyY74p3BJU_-a_mIq4GZyka2FlpnH4APVIfQ&code_challenge_method=S256', - callback_url: '********', - client_secret: '********', - code_verifier: '********', - refresh_token: '********', - headers: { - Authorization: 'Bearer ya29.-BhZtwh0ZLk-', - }, - queryParams: {}, - base_url: 'https://www.googleapis.com' +```python Python +# Unique identifier for the user for whom the connection is being created +entity_id = "Jessica" + +# Add the parameters collected from the user +collected_params = { + "api_key": "" } -``` - +# Initiate new connection (You can use integration_id instead of app) +connection_request = toolset.initiate_connection(connected_account_params=collected_params, entity_id=entity_id, app=App.FIRECRAWL) +# Check the status of the connection (it can be initiated, active, or failed) +print(connection_request.connectionStatus) +``` +```javascript Javascript +// Unique identifier for the user for whom the connection is being created +const entityId = "Jessica" - -You can fetch connection details after user is redirected back to your app. (If redirect was needed) +// Add the parameters collected from the user +const collectedParams = { + "api_key": "" +} -`connection_status` & `connectedAccountId` will be available in the query params. - - +// Initiate new connection (You can use integration_id instead of app) +const connectionRequest = await toolset.client.connectedAccounts.initiate({ + data: { + ...collectedParams + }, + entityId: entityId, + appName: "firecrawl", + authMode: "API_KEY", + authConfig: {}, + }); +// Check the status of the connection (it can be initiated, active, or failed) +console.log(connectionRequest.connectionStatus); +``` + + - -### Receiving Webhooks alerts on new Connections - -Composio provides real-time webhook notifications for new connections. To utilize this feature: - -1. Set up webhook alerts in the Composio dashboard -2. Configure your application to receive and parse the webhook payloads - -This allows you to instantly track when users integrate new services with your application. +Each App integration has a unique **integration ID**. You can use this ID instead of the **app name** when creating connections. + + \ No newline at end of file diff --git a/docs/patterns/Auth/examples/gmail_example.mdx b/docs/patterns/Auth/examples/gmail_example.mdx index 01acdd4a703..c017e7bd220 100644 --- a/docs/patterns/Auth/examples/gmail_example.mdx +++ b/docs/patterns/Auth/examples/gmail_example.mdx @@ -64,7 +64,7 @@ As stated in the output, you don't need to fetch any parameters from the user. S ```python Python Initiate connection # This is the URL that the user will be redirected to after completing the authentication process -redirect_url = "https://yourwebsite.com/connection/callback" +redirect_url = "https://yourwebsite.com/connection/success" # this is only useful for oauth based flows involving redirect based authentication. entity_id = "Jessica" # This is the unique identifier for the user @@ -92,17 +92,16 @@ else: ```javascript Javascript Initiate connection -const redirectUrl = "https://yourwebsite.com/connection/callback" +const redirectUrl = "https://yourwebsite.com/connection/success" const entityId = "Jessica" // This is the unique identifier for the user const connectionRequest = await toolset.client.connectedAccounts.initiate({ - data: { - ...collectedParams // send collected params - }, entityId: entityId, integrationId: expectedInputFields.integrationId, - redirectUri: redirectUrl + redirectUri: redirectUrl, + authMode: "OAUTH2", + authConfig: {}, }); if (connectionRequest.connectionStatus === "INITIATED") { diff --git a/docs/patterns/Auth/examples/shopify_example.mdx b/docs/patterns/Auth/examples/shopify_example.mdx index f07b8859b6c..36f884368ef 100644 --- a/docs/patterns/Auth/examples/shopify_example.mdx +++ b/docs/patterns/Auth/examples/shopify_example.mdx @@ -122,7 +122,7 @@ console.log(collectedParams); ```python Python Initiate connection # This is the URL that the user will be redirected to after completing the authentication process -redirect_url = "https://yourwebsite.com/connection/callback" +redirect_url = "https://yourwebsite.com/connection/success" # this is only useful for oauth based flows involving redirect based authentication. entity_id = "Jessica" # This is the unique identifier for the user @@ -150,7 +150,7 @@ else: ```javascript Javascript Initiate connection -const redirectUrl = "https://yourwebsite.com/connection/callback" +const redirectUrl = "https://yourwebsite.com/connection/success" const entityId = "Jessica" // This is the unique identifier for the user @@ -160,7 +160,9 @@ const connectionRequest = await toolset.client.connectedAccounts.initiate({ }, entityId: entityId, integrationId: expectedInputFields.integrationId, - redirectUri: redirectUrl + redirectUri: redirectUrl, + authMode: "OAUTH2", + authConfig: {}, }); if (connectionRequest.connectionStatus === "INITIATED") { diff --git a/docs/patterns/Auth/multiple-users.mdx b/docs/patterns/Auth/multiple-users.mdx deleted file mode 100644 index f16c51b7d24..00000000000 --- a/docs/patterns/Auth/multiple-users.mdx +++ /dev/null @@ -1,175 +0,0 @@ ---- -title: "Guide to User Management" -sidebarTitle: "Entities" -icon: "user" -description: "Guide to managing multiple users and their authentication using Composio." ---- - -## Introduction to Entities - -- **Each unique user** is represented by a **unique entity id**. -- If you have **two users, Jessica and Melissa**, they will have **unique entity ids**. - -## Introduction to Connected Accounts -- When a user connects their account, a `connected_account` object is created. -- This object securely stores **authentication data** such as **access tokens and refresh tokens**. - - -### Managing Entities - -To retrieve an entity object using code, you can use the following code: - - -```python Python Code Snippet to get an entity (user) -from composio import ComposioToolSet - -toolset = ComposioToolSet() -entity = toolset.get_entity(id='Jessica') -``` - -```javascript JS Code Snippet to get an entity (user) -import { OpenAIToolSet } from "composio-core"; - -const toolset = new OpenAI({ - apiKey: process.env.OPENAIKEY, - entityId: 'Jessica' -}); -const entity = toolset.client.getEntity(id='Jessica'); -``` - - - -You can use the entity object to manage the connected accounts for the user. You can also use the entity object to perform actions on behalf of the user and connect accounts for the user. - -### Getting Connected Accounts - -To get the connected accounts for an entity, you can use the following code: - -```python Python Code Snippet to get a connected account -try: - connected_accounts = entity.get_connections() #lists all connections of the entity - connected_accounts = entity.get_connection(app=App.GITHUB) #filters based on app name - connected_accounts = entity.get_connection(connected_account_id="9") #filters based on connected account id for an entity - print(connected_accounts) -except Exception as e: - print("No connected account found") -``` - -```javascript JS Code Snippet to get a connected account -try { - // filters based on connected account id for an entity - let connectedAccounts = await entity.connectedAccounts.get({connectedAccountId: '9'}) - - // filters connections based on appName for an entity - let connectedAccounts = tool_set.client.integrations.get({appName: 'github'}) - - // list all connections based on entityId - let connectedAccounts = await entity.connectedAccounts.list() - - console.log(connectedAccounts) -} catch (error) { - console.error('Error fetching connected accounts:', error.message) -} -``` - - -This code attempts to retrieve the connected account for Github. If no connected account is found, it catches the exception and prints a message. - -## Performing Actions on Behalf of Users - -Composio allows you to perform actions on behalf of users. - -### Executing Actions without an Agent on behalf of a user - -You can execute actions on behalf of a user without using an agent. - - -```python Python Execute Action without an agent -from composio import ComposioToolSet - -toolset = ComposioToolSet() -entity = toolset.get_entity(id='Jessica') - -res = entity.execute( - action=Action.GITHUB_GITHUB_API_ROOT, - params={}, -) -print(res) -``` - -```javascript JS Execute Action without an agent -import { OpenAIToolSet } from "composio-core"; - -const toolset = new OpenAIToolSet({ - apiKey: process.env.OPENAIKEY, - entityId: "Jessica" -}); - -const output = await toolset.client.actions.execute({ - actionName:'LINEAR_LIST_LINEAR_PROJECTS', - requestBody:{ - connectedAccountId: "", - input:{} - }, -}); -console.log(output); -``` - - -### Performing Actions with an Agent on behalf of a user - -You can use an agent to perform actions on behalf of a user. - - -```python Python Execute Action with an agent - -from composio_openai import ComposioToolSet, App -from openai import OpenAI - -openai_client = OpenAI(api_key="******OPENAIKEY******") -tool_set = ComposioToolSet(entity_id="Jessica") -actions = tool_set.get_tools(actions=["GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER"]) - -my_task = "Star the repo composiohq/composio on GitHub" - -response = openai_client.chat.completions.create( - model="gpt-4-turbo-preview", - tools=actions, - messages=[ - {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": my_task}, - ], -) -tool_set.handle_tool_calls(response=response, entity_id="Jessica") -``` - -```javascript JS Execute Action with an agent -import { OpenAI } from "openai"; -import { OpenAIToolSet } from "composio-core"; - -const openai_client = new OpenAI({ - apiKey: process.env.OPENAI_API_KEY -}); - -const toolset = new OpenAIToolSet({ - apiKey: process.env.COMPOSIO_API_KEY, -}); - -const tools = await toolset.getTools({actions: ['GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER']}) - -const task = "Star the repo composiohq/composio on GitHub" - -const response = await openai_client.chat.completions.create({ - model: "gpt-4-turbo-preview", - tools: tools, - messages: [ - {role: "system", content: "You are a helpful assistant."}, - {role: "user", content: task}, - ], -}); - -await toolset.handleToolCall(response, "Jessica"); -``` - - -In this example, an agent is configured to star a repository on GitHub on behalf of the user. The OpenAI API is used to process the request and perform the action. diff --git a/docs/patterns/Auth/using-connections.mdx b/docs/patterns/Auth/using-connections.mdx new file mode 100644 index 00000000000..133ed321362 --- /dev/null +++ b/docs/patterns/Auth/using-connections.mdx @@ -0,0 +1,156 @@ +--- +title: "How to use Connections?" +sidebarTitle: "Using Connections" +icon: "file-user" +description: "Learn how to use connections" +--- + +### Get all connected accounts for an entity + + ```python Python + from composio import ComposioToolSet, App + toolset = ComposioToolSet() + + # Filter based on entity id + entity = toolset.get_entity(id="Jessica") + try: + # Lists all connections of the entity + connected_accounts = entity.get_connections() + print(connected_accounts) + except NoItemsFound as e: + print("No connected account found") + ``` + ```javascript JavaScript + import { OpenAIToolSet } from "composio-core"; + const toolset = new OpenAIToolSet(); + + // Filter based on entity id + const entity = await toolset.client.getEntity("Jessica") + + // lists all connections of the entity + const connected_accounts = await entity.getConnections() + + if (connected_accounts.length > 0) { + console.log(connected_accounts) + }else{ + console.log("No connected account found") + } + ``` + + +### Check if an entity has a connected account for a particular app + + ```python Python + from composio import ComposioToolSet, App + from composio.client.exceptions import NoItemsFound + + toolset = ComposioToolSet() + + # Filter based on entity id + entity = toolset.get_entity(id="Jessica") + + try: + # Filters based on app name + connection_details = entity.get_connection(app=App.GITHUB) + # Filters based on connected account id for an entity + connection_details = entity.get_connection(connected_account_id="") + print(connection_details) + except NoItemsFound as e: + print("No connected account found") + ``` + ```javascript JavaScript + import { OpenAIToolSet } from "composio-core"; + const toolset = new OpenAIToolSet(); + + // Filter based on entity id + const entity = await toolset.client.getEntity("Jessica") + + // Filters based on app name + const connectionDetails = await entity.getConnection("github") + + if(connectionDetails){ + console.log(connectionDetails) + }else{ + console.log("No connection details found") + } + ``` + + +### Fetch the Connection Parameters +You can use connection parameters locally to build custom actions. The following parameters are typically available: + +- `status`: Current state of the connection (`initiated`, `active`, or `failed`) +- `refresh_token`: Token used to obtain new access tokens +- `expires_in`: Token expiration time in seconds +- `token_type`: Type of token (usually "Bearer") +- `base_url`: Base URL for API requests +- Additional parameters specific to the connected service + + +```python Python +connected_account = toolset.get_connected_account(connection_request.connectedAccountId) + +# Get the parameters for your local usage +print(toolset.get_auth_params(connection_id=connected_account.id)) + +#print(connected_account.connectionParams) # use this for raw/advanced cases +``` + +```javascript JavaScript +const connectedAccount = await toolset.client.connectedAccounts.get({ + connectedAccountId: connectionRequest.connectedAccountId +}) + +const connectedAccountAuthParams = await toolset.getAuthParams({ + connectedAccountId: connectedAccount.connectedAccountId +}) + +console.log("Connected account auth params", connectedAccountAuthParams) + +//console.log("Connected account raw auth params", connectedAccount.connectionParams) + +``` + + +Example of how connection params would look like + + +``` JSON Auth Params Output +{ + "base_url": "", // This is the base URL for the API Ex. https://api.linear.app + "params": [{ // This is the list of all the params + "name": "x-api-key", + "in": "header", // `in` value could be of type `header`, `query` + "value": "" + }], + "body": {} +} +``` +``` Javascript Raw Auth Params Output +Connected account raw auth params { + scope: '********', + scopes: '********', + id_token: '********', + client_id: '********', + expires_in: '********', + token_type: '********', + redirectUrl: 'https://accounts.google.com/o/oauth2/v2/auth?client_id=96-8p515bt7ijf94c2bf4a5lev5jr6r7oc1.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fbackend.composio.dev%2Fapi%2Fv1%2Fauth-apps%2Fadd&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgmail.modify&response_type=code&access_type=offline&prompt=consent&state=staging_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.30.W9PV-ncrbbPhnjfcgBCN8ZNn9A8V2lzCbXQR2fOXht4&code_challenge=YpyY74p3BJU_-a_mIq4GZyka2FlpnH4APVIfQ&code_challenge_method=S256', + callback_url: '********', + client_secret: '********', + code_verifier: '********', + refresh_token: '********', + headers: { + Authorization: 'Bearer ya29.-BhZtwh0ZLk-', + }, + queryParams: {}, + base_url: 'https://www.googleapis.com' +} +``` + + + + + + +You can fetch connection details after user is redirected back to your app (If redirect was needed) and `connectionStatus` & `connectedAccountId` will be available in the query params. + \ No newline at end of file diff --git a/docs/patterns/actions/action-guide-faqs.mdx b/docs/patterns/actions/action-guide-faqs.mdx deleted file mode 100644 index ab1a56dba2d..00000000000 --- a/docs/patterns/actions/action-guide-faqs.mdx +++ /dev/null @@ -1,130 +0,0 @@ ---- -title: "πŸ› οΈ What else can I do with Actions?" -sidebarTitle: "Actions - FAQs" -icon: "wand-magic-sparkles" -description: "Understand more about Actions" ---- - - - - -```python Python Selecting Actions via Name -tool_set = ComposioToolSet() - -tools = tool_set.get_tools(actions=[Action.GITHUB_CREATE_AN_ISSUE,Action.GITHUB_COMMIT_EVENT]) -# can pass multiple actions -``` - -```javascript Javascript Selecting Actions via Name -const toolset = new OpenAIToolSet(); - -const tools = await toolset.getTools({actions: ['github_issues_create','github_commit_event']}); -// can pass multiple actions -``` - - - - - - - - -```Python Python Selecting Actions -use_case="Star a repo on github" - -action_enums=tool_set.find_actions_by_use_case(App.GITHUB,use_case=use_case) - -tools = tool_set.get_tools(actions=action_enums) - -# use tools as per your framework -``` - -```Javascript Javascript Selecting Actions -import { LangchainToolSet } from "composio-core"; - -const toolset = new LangchainToolSet({ - entityId: "default", -}); - -const actionsList = await toolset.client.actions.list({ - useCase: "create github issues", - apps: "github", -}); -``` - -```bash CLI Selecting Actions -composio actions --use-case 'get channel messages' --app 'slack' -``` - - - - - - - - - - -```python Selecting Actions via Apps & Tags -tools = tool_set.get_tools(apps=[App.GITHUB]) - -# Filter by tags -tag = "users" - -action_enums = toolset.find_actions_by_tags( - App.GITHUB, - tags=[tag], -) - -tools = tool_set.get_tools(actions=action_enums) -``` - - - - - -```javascript Selecting Actions via Apps -import { LangchainToolSet } from "composio-core"; - -const toolset = new LangchainToolSet({ - apiKey: process.env.COMPOSIO_API_KEY, - entityId: "default" -}); - -const actionsList = await toolset.client.actions.list({ - apps: "github" -}); - -const actions = await toolset.getTools({ - actions: actionsList.items.map((action) => { - return action.name; - }) -}) -``` - - - - - -```bash Selecting Actions via Apps -composio actions --app 'github' --tag 'code' -# Don't use tag if you want all actions -``` - - - - - - - - - -```curl curl -curl --request GET \ - --url https://backend.composio.dev/api/v2/actions \ - --header 'X-API-Key: ' -``` - - - - diff --git a/docs/patterns/actions/action-guide-with-agents.mdx b/docs/patterns/actions/action-guide-with-agents.mdx deleted file mode 100644 index 8d1864f0566..00000000000 --- a/docs/patterns/actions/action-guide-with-agents.mdx +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: "πŸ› οΈ How can I execute Actions with my AI Agent?" -sidebarTitle: "Execute Actions with Agents" -icon: "robot" -description: "Perform Actions with your account or on behalf of your users with Agents" ---- -## Using Actions - -Composio lets you perform actions with your account or on behalf of your users. Feel free to check all the [tools](https://app.composio.dev/apps) we support. - -### Execute Actions with Agents - -To execute actions with your account or on behalf of your users, you can use the following code. - - -```python Python -from langchain.agents import create_openai_functions_agent, AgentExecutor -from langchain import hub -from langchain_openai import ChatOpenAI -from composio_langchain import ComposioToolSet, Action, App -import os - - -llm = ChatOpenAI(model="gpt-4o") - -prompt = hub.pull("hwchase17/openai-functions-agent") - -# Get All the tools -tool_set = ComposioToolSet() -tools = tool_set.get_tools(actions=[Action.GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER], tags=[]) - -# Define task -task = "Star a repo composiohq/composio on GitHub" - -agent = create_openai_functions_agent(llm, tools, prompt) -agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) - -# Execute using agent_executor -agent_executor.invoke({"input": task}) -``` - -```javascript JavaScript - import { LangchainToolSet } from "composio-core"; - import { ChatOpenAI } from "@langchain/openai"; - import { AgentExecutor, createOpenAIFunctionsAgent } from "langchain/agents"; - import { pull } from "langchain/hub"; - - - (async () => { - const llm = new ChatOpenAI({ model: "gpt-4-turbo" }); - const composioToolset = new LangchainToolSet({ apiKey: process.env.COMPOSIO_API_KEY }); - const tools = await composioToolset.getTools({ actions: ["github_issues_create"] }); - const prompt = await pull("hwchase17/openai-functions-agent"); - - const agent = await createOpenAIFunctionsAgent({ llm, tools, prompt }); - const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); - const issueDetails = { - TITLE: "Sample issue", - DESCRIPTION: "Sample issue for the repo - himanshu-dixit/custom-repo-breaking" - }; - - const result = await agentExecutor.invoke({ - input: `Create a GitHub issue with the following details: ${JSON.stringify(issueDetails)}` - }); - return result.output; - })(); - ``` - - -This code demonstrates how to use LLMs to execute an action. -Composio supports multiple frameworks for creating Agents including LlamaIndex, CrewAI, Letta, Langchain, you can see it in the **Supported Frameworks** section. diff --git a/docs/patterns/actions/action-guide-without-agents.mdx b/docs/patterns/actions/action-guide-without-agents.mdx deleted file mode 100644 index 34e56011759..00000000000 --- a/docs/patterns/actions/action-guide-without-agents.mdx +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: "πŸ› οΈ How can I execute Actions without my AI Agent?" -sidebarTitle: "Execute Actions without Agents" -icon: "fax" -description: "Perform Actions with your account or on behalf of your users without Agents" ---- - -## Using Actions - -Composio lets you perform actions with your account or on behalf of your users. Feel free to check all the [tools](https://app.composio.dev/apps) we support. - -### Execute Actions without Agents - -To execute actions without using Agents, you can manually supply the parameters to execute the action or use natural language. - - - ```python Python Star a repo -from composio import ComposioToolSet, Action - -tool_set = ComposioToolSet(entity_id="Jessica") -#If you did not run 'composio login' in the CLI, you can use API Key like this: -#tool_set = ComposioToolSet(api_key, entity_id="Jessica") - -#You can change the repo you want to star by modifying the parameters -tool_set.execute_action( - action=Action.GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER, - params={"owner": "composiohq", "repo": "composio"}, - entity_id="Jessica", -) -``` - -```javascript JavaScript Get Hypermedia links in GitHub -import { OpenAIToolSet } from "composio-core"; - -const toolset = new OpenAIToolSet(); - -const customAuthAction = await toolset.client.actions.execute({ - actionName: "GITHUB_GITHUB_API_ROOT", - requestBody: { - appName: "github", - authConfig: { - parameters: [{ - name: "Authorization", - in: "header", - value: `Bearer YOUR_API_KEY` - }] - }, - input: {} - } -}); - -console.log("Custom auth action response", customAuthAction) - ``` - - -## Execute Actions with Natural Language -You can also execute Actions by passing in natural language prompts without specific parameters - -```python Python - tool_set.execute_action( - action=Action.GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER, - params={}, - text="Star the repo composiohq/composio", - entity_id="Jessica", - ) -``` - -```javascript JavaScript - await toolset.getEntity("Jessica").execute( - 'github_star_a_repository_for_the_authenticated_user', - {}, - "Star the repo composiohq/composio" - ); -``` - - -
\ No newline at end of file diff --git a/docs/patterns/actions/custom_actions.mdx b/docs/patterns/actions/custom_actions.mdx deleted file mode 100644 index c1705a2781c..00000000000 --- a/docs/patterns/actions/custom_actions.mdx +++ /dev/null @@ -1,269 +0,0 @@ ---- -title: "Custom Actions" -sidebarTitle: "Building Custom Actions" -icon: "hammer" -description: "Guide to creating Custom Actions for existing tool or new tool" ---- - -## What are Custom Actions? - -- Extend the functionality of existing tools by creating a custom action which utilises the existing authentication. (Fetch emails from Gmail) -- Write a custom action code snippet to execute the custom action (Check if number is even or odd) - - - -Custom Actions can be created for any existing tool in Composio, allowing you to tailor the functionality to your specific needs while leveraging the existing authentication. - - -## Creating a Custom Action - - - - - -```python Python -from composio import ComposioToolSet, App, action - -toolset = ComposioToolSet() -``` -```javascript Javascript -import { OpenAIToolSet } from "composio-core" -import { z } from "zod" - -const toolset = new OpenAIToolSet({}) -``` - - - - - - -As `gmail` toolname is already registered in Composio, `auth` dictionary will be automatically provided! - - -```python Custom Action - Gmail (python) -@action(toolname="gmail", requires=["example-pypi-package"]) # supports any package -def my_custom_action(auth: dict, account_id: str) -> str: # Uses existing gmail auth - """ - Fetch emails from Gmail account for last 24 hours - - :param account_id: Account ID, pass 'me' for default account - :param auth: Authentication dictionary provided by Composio for Gmail - :return info: Gmail emails information - """ - - # fetch authentication headers - headers = auth["headers"] - query_params = auth["query_params"] - base_url = auth["base_url"] - - yesterday_dateTime = int( - (datetime.datetime.now() + datetime.timedelta(days=-1)).timestamp() - ) - - if account_id and account_id != "": - custom_endpoint_url = f"/gmail/v1/users/{account_id}/messages?q=after:{yesterday_dateTime}" - else: - custom_endpoint_url = f"/gmail/v1/users/me/messages?q=after:{yesterday_dateTime}" - - # add query params to the url - for key, value in query_params.items(): - custom_endpoint_url += f"&{key}={value}" - - url = f"{base_url}{custom_endpoint_url}" - - response = requests.get(url, headers=headers) - - if response.status_code == 200: - print("Successfully fetched emails:", response.json()) - else: - print("Error fetching emails:", response.status_code, response.json()) - return str(response) -``` - -```javascript Custom Action - Gmail (javascript) -await toolset.createAction({ - actionName: "myCustomAction", - toolName: "gmail", - description: "Fetch emails from Gmail account for last 24 hours", - inputParams: z.object({ - accountId: z.string().describe("Gmail account ID. Defaults to the primary account, which is 'me'."), - }), - callback: async (inputParams, authCredentials) => { - const headers = authCredentials.headers; - const query_params = authCredentials.query_params; - const base_url = authCredentials.baseUrl; - - const oneDayAgo = Math.floor(Date.now() / 1000) - 86400; - const customEndpointUrl = `/gmail/v1/users/${inputParams.accountId}/messages?q=after:${oneDayAgo}`; - const url = `${base_url}${customEndpointUrl}`; - const response = await fetch(url, { headers }); - - if (response.ok) { - const data = await response.json(); - console.log("Successfully fetched emails:", data); - return data; - } else { - const errorData = await response.json(); - console.error("Error fetching emails:", response.status, errorData); - throw new Error(`Error fetching emails: ${response.status}`); - } - } -}); -``` - - - - - -```python Python -@action(toolname="cow", requires=["cowsay"]) -def my_custom_action(account_id: str) -> str: - """ - Cow will say whatever you want it to say. - - :param account_id: Account ID, pass 'me' for default account - :return greeting: Formatted message. - """ - import cowsay - - return cowsay.get_output_string("cow", account_id) -``` -```javascript JavaScript -await toolset.createAction({ - actionName: "myCustomAction", - description: "Cow will say whatever you want it to say. This can be used to print text in cow style", - inputParams: z.object({ - accountId: z.string() - }), - callback: async (inputParams) => { - const accountId = inputParams.accountId; - const cowMessage = `Cow says: ${accountId}`; - return cowMessage; - } -}); -``` - - - - - - -We can execute the custom action without Agents as well - - - -```python Python -from composio import ComposioToolSet - -toolset = ComposioToolSet() -toolset.execute_action( - action=my_custom_action, - params={ - 'account_id':'me' - }, -) -``` - -```javascript JavaScript -console.log( - await toolset.executeAction( - "myCustomAction", - { accountId: "me" } - ) -) -``` - - - - -```python Python Executing Custom Action with Agent -from openai import OpenAI -from composio_openai import ComposioToolSet - -openai_client = OpenAI() -# Initialise the Composio Tool Set -composio_toolset = ComposioToolSet() - -# Get GitHub tools that are pre-configured -# Retrieve actions -actions = composio_toolset.get_tools(actions=[my_custom_action]) - -my_task = "Fetch emails from Gmail account for last 24 hours" - -# Setup openai assistant -assistant_instruction = "You are a super intelligent personal assistant" - -# Prepare assistant -assistant = openai_client.beta.assistants.create( - name="Personal Assistant", - instructions=assistant_instruction, - model="gpt-4-turbo-preview", - tools=actions, # type: ignore -) - -# create a thread -thread = openai_client.beta.threads.create() -message = openai_client.beta.threads.messages.create( - thread_id=thread.id, role="user", content=my_task -) - -# Execute Agent with integrations - -run = openai_client.beta.threads.runs.create( - thread_id=thread.id, assistant_id=assistant.id -) - -# Execute function calls -response_after_tool_calls = composio_toolset.wait_and_handle_assistant_tool_calls( - client=openai_client, - run=run, - thread=thread, -) - -url = f"https://platform.openai.com/playground/assistants?assistant={assistant.id}&thread={thread.id}" - -print("Visit this URL to view the thread: ", url) -``` - -```javascript Javascript Custom Action with Agent -const tools = await toolset.getTools({ actions: ["myCustomAction"] }); -const instruction = "Fetch emails from Gmail account for last 24 hours" - -const client = new OpenAI({ apiKey: process.env.OPEN_AI_API_KEY }) -const response = await client.chat.completions.create({ - model: "gpt-4-turbo", - messages: [{ - role: "user", - content: instruction, - }], - tools: tools, - tool_choice: "auto", -}) - -console.log("Result", await toolset.handleToolCall(response)); -``` - - - - - -Output from executing Custom Action without Agents - -```shell Output from executing Custom Action without Agents -[INFO] Logging is set to INFO, use `logging_level` argument or `COMPOSIO_LOGGING_LEVEL` change this -[INFO] Executing `GMAIL_MY_CUSTOM_ACTION` with params={'query': 'test_query'} and metadata=None connected_account_id=None -[INFO] Got response={'data': {'info': {'headers': {'Authorization': 'Bearer KEY', 'x-request-id': '2c65e8b'}, 'base_url': 'https://api.github.com', 'query_params': {}}}, 'error': None, 'successful'... -{'data': {'info': {'headers': {'Authorization': 'Bearer KEY', 'x-request-id': '2c65e8b'}, 'base_url': 'https://api.github.com', 'query_params': {}}}, 'error': None, 'successful': True} -``` - - - - -### Why Use Custom Actions? - -Custom Actions provide several advantages: - -- **Data privacy:** Execution happens on the user’s machine, ensuring sensitive data doesn’t leave the local environment. -- **Flexibility:** Users can create and customize as many tools and actions as needed. -- **Compatibility:** Custom actions can be integrated seamlessly across various Composio-supported platforms. diff --git a/docs/patterns/actions/usecase.mdx b/docs/patterns/actions/usecase.mdx deleted file mode 100644 index 538d8b61d59..00000000000 --- a/docs/patterns/actions/usecase.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: "Finding Actions by Use Case" -sidebarTitle: "Actions by Use Case" -icon: "magnifying-glass" -description: "This documentation will guide you through the process of use case-based action finding in Composio." ---- - -Find relevant actions for your use case by describing what you want to accomplish in natural language. - -This approach is crucial because AI agents typically perform best with a limited set of actions. - - - -```Python Python Fetch Actions using use-case -use_case="Star a repo on github" - -action_enums=toolset.find_actions_by_use_case(App.GITHUB, use_case=use_case) -tools = toolset.get_tools(actions=action_enums) # use tools as per your framework -``` - -```Javascript Javascript Fetch Actions using use-case -import { LangchainToolSet } from "composio-core"; - -const toolset = new LangchainToolSet({ - entityId: "default", -}); - -const actionsList = await toolset.client.actions.list({ - useCase: "create github issues", - apps: "github", -}); -``` - -```bash CLI Fetch Actions using use-case -composio actions --use-case 'get channel messages' --app 'slack' -``` - \ No newline at end of file diff --git a/docs/patterns/functions/triggers.mdx b/docs/patterns/functions/triggers.mdx deleted file mode 100644 index 423b7ebdd91..00000000000 --- a/docs/patterns/functions/triggers.mdx +++ /dev/null @@ -1,165 +0,0 @@ ---- -title: "Enabling a Specific Trigger for a User in Composio" -sidebarTitle: "Specific Triggers for a User" -icon: "webhook" -description: "This guide provides step-by-step instructions for enabling a specific trigger for a user in Composio." ---- - -### Prerequisites - -1. Get the trigger name and required config from the UI: This step is common across all users. -2. Set the webhook URL: This should be done once for a Composio account. -3. Enable the trigger for the user: This is done for each user. - -### Step 1: Set Up the Composio Client - -First, initialize the Composio client using your API key. - -```python python -from composio import Composio, App - -composio_client = Composio(api_key="API_KEY") -``` -```javascript javascript -import { OpenAIToolSet } from "composio-core"; - -const toolset = new OpenAIToolSet({ - apiKey: process.env.COMPOSIO_API_KEY, -}); -``` - - -### Step 2: Define User and Trigger Information - -Specify the user and trigger details. Replace entity_id and selected_app with the relevant user ID and app. - -```python python -entity_id = "soham" # Unique user identifier in your app -selected_app = App.GITHUB # The app you are working with -trigger_name = "github_commit_event" # Trigger name from Composio UI -trigger_config = {"owner": "composiohq", "repo": "composio"} # Trigger config from Composio UI -``` -```javascript javascript -const entity_id = "soham" // Unique user identifier in your app -const selected_app = "github" // The app you are working with -const trigger_name = "github_commit_event" // Trigger name from Composio UI -const trigger_config = {"owner": "composiohq", "repo": "composio"} // Trigger config from Composio UI -``` - - - -### Step 3: Retrieve User Entity and Connection - -Get the user entity and check the connection to the specified app. - -```python python -entity = composio_client.get_entity(id=entity_id) -connected_account = entity.get_connection(app=selected_app) # Get connected account -``` -```javascript javascript -const entity = toolset.client.getEntity(id=entity_id); -const connected_account = await entity.getConnection(selected_app); // Get connected account -``` - - - -### Step 4: Retrieve and Verify Trigger -Fetch the trigger using its name and verify if it exists. - - -```python python -triggers = composio_client.triggers.get(trigger_names=[trigger_name]) # Get the triggers - -if len(triggers) == 0: - raise Exception("Trigger not found") # Handle incorrect trigger name -``` -```javascript javascript -const triggersData = await toolset.client.activeTriggers.list({ - triggerIds: [trigger_id].join(",") // separated by comma -}); // Get the active triggers - -if (triggersData.triggers?.length === 0) { - throw new Error("Trigger not found"); // Handle incorrect trigger name -} - -``` - - -### Step 5: Check for Active Triggers -Check if the trigger is already enabled for the user. - -```python python -active_triggers = composio_client.active_triggers.get( - trigger_names=[trigger_name], connected_account_ids=[connected_account.id] -) - -if len(active_triggers) > 0: - print(f"Trigger {trigger_name} is already enabled") - exit() -``` - - -### Step 6: Enable the Trigger -Enable the trigger for the user with the specified configuration. - - -```python python -print("Trigger config - ", trigger_config) - -entity.enable_trigger( - trigger_name=trigger_name, app=selected_app, config=trigger_config -) - -print(f"Trigger {trigger_name} enabled") -``` - - - - -### Ensuring the User is Connected to the App -If the user is not connected to the app, the connection must be established. The following script helps to ensure the user is connected. - - -```python python -from composio import Composio, App - -composio_client = Composio(api_key="API_KEY") - -# get the user id -entity_id = "Soham" # Unique ID for the user -app = App.GITHUB - -entity = composio_client.get_entity(id=entity_id) - -try: - print("Checking if user is connected to app...") - connection = entity.get_connection(app=app) - if connection: - print("User is connected to app") -except Exception as e: - connection = None - -if not connection: - print("No connection found") - print("Initiating connection...") - connection_request = entity.initiate_connection( - app_name=app, redirect_url="https://www.google.com" - ) # Redirect URL is optional - - if connection_request.redirectUrl: - print(f"Please visit {connection_request.redirectUrl} to connect {app}") - else: - print(f"Please provide your credentials to connect {app}") - - connection_request.wait_until_active(client=composio_client, timeout=60) - # Polling until connection is active with a 60-second timeout - -print(f"User is already connected to {app}") -# Connection object is now available - -``` - - - -### Conclusion -By following these steps, you can efficiently enable a specific trigger for a user in Composio, ensuring that the necessary app connections are established and maintained. This guide provides a structured approach to managing triggers and connections, enhancing the capabilities of your Composio setup. \ No newline at end of file diff --git a/docs/patterns/tools/build-tools/custom-action-with-auth.mdx b/docs/patterns/tools/build-tools/custom-action-with-auth.mdx new file mode 100644 index 00000000000..714e8b25dd0 --- /dev/null +++ b/docs/patterns/tools/build-tools/custom-action-with-auth.mdx @@ -0,0 +1,175 @@ +--- +title: "Build Tools with Auth" +sidebarTitle: "Build Tools with Auth" +icon: "toolbox" +description: "Create custom actions that leverage existing tool authentication to extend functionality." +--- + + +Custom Actions are powerful building blocks that enable you to create custom functionality while leveraging existing tool authentication. + + +## Creating a Custom Action with Authentication + + + + + + + +```bash Python +pip install composio_openai openai +``` + +```bash JavaScript +npm install composio-core openai +``` + + + + + +```python Python +import typing as t +from composio_openai import ComposioToolSet, action, Action +from openai import OpenAI + +openai_client = OpenAI() +toolset = ComposioToolSet() +``` +```javascript JavaScript +import { OpenAI } from "openai"; +import { OpenAIToolSet } from "composio-core"; +import { z } from "zod"; + +const openai_client = new OpenAI(); +const openAIToolset = new OpenAIToolSet(); +``` + + + + +Below are examples of creating a custom action called `list_repositories` (Python) & `star_repo` (JavaScript) that integrates with the `github` tool. + +You need to add the action, input parameters & return content description, this is what the LLM will use to understand the action. + +The `execute_request/executeRequest` method is used to make API calls, it accepts the following arguments: +- `endpoint`: Endpoint URL. The base URL of the API will be prepended to this. You can find it in your connection's **Connection Info** section +- `method`: HTTP method to use +- `body`: Request body to pass to the API +- `parameters`: Custom Authentication Parameters +- `connection_id`: ID of the connected account + + +Since `github` is a registered tool in Composio, the authentication credentials are automatically injected into your custom action! + + +```python Python +@action(toolname="github") +def list_repositories( + owner: str, + execute_request: t.Callable, +) -> list[str]: + """ + List repositories for a user. + + :param owner: Name of the owner. + :return repositories: List of repositories for given user. + """ + return [ + repo["name"] + for repo in execute_request(f"/users/{owner}/repos", "get", None, None).get( + "data", [] + ) + ] +``` + +```javascript JavaScript +const action = await openAIToolset.createAction({ + actionName: "star_repo", + toolName: "github", + description: "Stars a repository on GitHub", + inputParams: z.object({ + owner: z.string().describe("The owner of the repository"), + repo: z.string().describe("The name of the repository"), + }), + callback: async (inputParams, authCredentials, executeRequest) => { + try { + const res = await executeRequest({ + endpoint: `/user/starred/${inputParams.owner}/${inputParams.repo}`, + method: "PUT", + parameters: [], + body: {} + }); + return res; + } catch (e) { + console.error(e); + return {}; + } + }, +}) +``` + + + + +Executing the custom action using LLM. Learn how to execute the custom action without LLM [here](/patterns/tools/use-tools/action-guide-without-agents#how-to-execute-custom-actions-directly). + +```python Python +tools = toolset.get_tools(actions=[list_repositories]) + +task = "List all the repositories for the organization composiohq" + +response = openai_client.chat.completions.create( +model="gpt-4o-mini", +tools=tools, +messages= + [ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": task}, + ], +) + +result = toolset.handle_tool_calls(response) +print(result) +``` + +```javascript JavaScript +const tools = await openAIToolset.getTools({ + actions: ["star_repo"] +}); + +const task = "Star the repository composioHQ/composio"; + +const response = await openai_client.chat.completions.create({ + model: "gpt-4o-mini", + messages: [ + { "role": "system", "content": "You are a helpful assistant." }, + { "role": "user", "content": task }, + ], + tools: tools, + tool_choice: "auto", +}); + +const result = await openAIToolset.handleToolCall(response, "default"); +console.log(result); +``` + + + + +### Why Use Custom Actions? + +Custom Actions provide several advantages: + +- **Data privacy:** Execution happens on the user’s machine, ensuring sensitive data doesn’t leave the local environment. +- **Flexibility:** Users can create and customize as many tools and actions as needed. +- **Compatibility:** Custom actions can be integrated seamlessly across various Composio-supported platforms. diff --git a/docs/patterns/tools/build-tools/custom-action-without-auth.mdx b/docs/patterns/tools/build-tools/custom-action-without-auth.mdx new file mode 100644 index 00000000000..ac62dc67bab --- /dev/null +++ b/docs/patterns/tools/build-tools/custom-action-without-auth.mdx @@ -0,0 +1,138 @@ +--- +title: "Build Tools Without Auth" +sidebarTitle: "Build Tools Without Auth" +icon: "plus" +description: "Create standalone custom tools and actions for any functionality you need (e.g., data processing, calculations, or integrations with other services)" +--- + + +Custom Actions are powerful building blocks that enable you to create custom functionality while running independently. They can handle everything from simple data processing to complex third-party integrations. + + +## Creating a Custom Tool without Authentication + + + + + +```python Python +from composio_openai import ComposioToolSet, action +from openai import OpenAI + +openai_client = OpenAI() +toolset = ComposioToolSet() +``` +```javascript JavaScript +import { OpenAIToolSet } from "composio-core" +import { OpenAI } from "openai"; +import { z } from "zod" + +const openai_client = new OpenAI(); +const toolset = new OpenAIToolSet(); +``` + + + +Below are examples of creating a custom action called `my_custom_action` (Python) & `myCustomAction` (JavaScript) to make cowsay say whatever you want it to say. + +You need to add the action, input parameters & return content description, this is what the LLM will use to understand the action. + +```python Python +@action(toolname="cow", requires=["cowsay"]) +def my_custom_action(message: str) -> str: + """ + Cow will say whatever you want it to say. + + :param message: Message to be displayed + :return greeting: Formatted message. + """ + import cowsay + + return cowsay.get_output_string("cow", message) +``` +```javascript JavaScript +await toolset.createAction({ + actionName: "myCustomAction", + description: "Cow will say whatever you want it to say", + inputParams: z.object({ + message: z.string() + }), + callback: async (inputParams) => { + const message = inputParams.message; + const cowMessage = `Cow says: ${message}`; + return cowMessage; + } +}); +``` + + + +Executing the custom action using LLM. Learn how to execute the custom action without LLM [here](/patterns/tools/use-tools/action-guide-without-agents#how-to-execute-custom-actions-directly). + +```python Python +tools = toolset.get_tools(actions=[my_custom_action]) + +task = "Say 'AI is the future' using cowsay" + +response = openai_client.chat.completions.create( +model="gpt-4o-mini", +tools=tools, +messages= + [ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": task}, + ], +) + +result = toolset.handle_tool_calls(response) +print(result) +``` + +```javascript JavaScript +const tools = await toolset.getTools({ + actions: ["myCustomAction"] +}); + +const instruction = "Say 'AI is the future' using cowsay"; + +const response = await openai_client.chat.completions.create({ + model: "gpt-4o-mini", + messages: [{ role: "user", content: instruction }], + tools: tools, + tool_choice: "auto", +}); + +const result = await toolset.handleToolCall(response); +console.log(result); +``` + + +Output from executing Custom Action + +```shell Python + ________________ +| AI is the future | + ================ + \ + \ + ^__^ + (oo)\_______ + (__)\ )\/\ + ||----w | + || || +``` +```shell JavaScript +Cow says: AI is the future +``` + + + + + +### Why Use Custom Tools or Actions? + +Custom Tools or Actions provide several advantages: + +- **Data privacy:** Execution happens on the user’s machine, ensuring sensitive data doesn’t leave the local environment +- **Flexibility:** Users can create and customize as many tools and actions as needed +- **Compatibility:** Custom actions can be integrated seamlessly across various Composio-supported platforms diff --git a/docs/introduction/foundations/components/integrations/custom-integration.mdx b/docs/patterns/tools/custom-integration.mdx similarity index 92% rename from docs/introduction/foundations/components/integrations/custom-integration.mdx rename to docs/patterns/tools/custom-integration.mdx index f84d5708dbf..6b9a01460e2 100644 --- a/docs/introduction/foundations/components/integrations/custom-integration.mdx +++ b/docs/patterns/tools/custom-integration.mdx @@ -1,18 +1,18 @@ --- -title: "πŸ”§ Adding Custom Tools" -sidebarTitle: "Custom Tools" +title: "πŸ”§ How to add your own App?" +sidebarTitle: "Add Your Own App" icon: "puzzle-piece" -description: "Explore the process of creating custom tools with external Apps using OpenAPI Spec" +description: "Learn how to add your own App to Composio" --- -Creating custom tools on Composio is straightforward and can be done via an [OpenAPI Spec](https://swagger.io/specification/). +Creating your own App on Composio is straightforward and can be done via an [OpenAPI Spec](https://swagger.io/specification/). -Here's a tutorial showing how to create a Custom Tool for Notion +Here's a tutorial showing how to add Notion as an App on Composio + +1. Navigate to the [API Section](/api-reference/actions/get-action) of our documentation +2. Click on **Get Action** under the **Actions** category +3. Enter your Composio API key and the Action ID +4. The **parameters** attribute in the response contains the required parameters for executing the action + + + \ No newline at end of file diff --git a/docs/patterns/tools/use-tools/processing-actions.mdx b/docs/patterns/tools/use-tools/processing-actions.mdx new file mode 100644 index 00000000000..2b44b745ba1 --- /dev/null +++ b/docs/patterns/tools/use-tools/processing-actions.mdx @@ -0,0 +1,164 @@ +--- +title: "πŸ› οΈ How to modify Actions?" +sidebarTitle: "Modify Actions" +icon: "wand-magic-sparkles" +description: "Learn how to modify Tools & Actions to refine schemas, inputs, and outputs for optimal results." +--- + + +## Refining Tool Schemas, Inputs, & Outputs + +In many scenarios, the schemas, inputs, or outputs of tools may benefit from additional processing. This refinement step can significantly improve the quality and usability of your data. Here are three key use cases: + +- **Modifying Schema**: Modify the tool schema like the description of the parameters or the default values. For example, if you're manually providing certain values in input (like project_id), you can mark these fields as "not required" in the schema so the LLM knows it doesn't need to ask for them. +- **Modifying Inputs**: Add values as inputs to avoid specifying them in the prompt. e.g., passing `project_id` & `team_id` to the `LINEAR_CREATE_LINEAR_ISSUE` action. +- **Modifying Outputs**: Modify outputs to get the desired data. e.g., extracting `execution_id` & `issue_id` from the response of `LINEAR_CREATE_LINEAR_ISSUE` action. Doing this can help keep the LLM context clean. + +Composio empowers you with the ability to define **custom functions** as schema modifiers, input modifiers, or output modifiers. + +These can be applied at two levels: + +1. **App-level**: Affects all actions within a specific tool. +2. **Action-level**: Tailored processing for individual actions. + + + + + +```python Python +from langchain.agents import create_openai_functions_agent, AgentExecutor +from langchain import hub +from langchain_openai import ChatOpenAI +from composio_langchain import ComposioToolSet, Action, App +``` +```javascript JavaScript +Coming Soon +``` + + + + +```python Python +prompt = hub.pull("hwchase17/openai-functions-agent") + +llm = ChatOpenAI() +composio_toolset = ComposioToolSet() +``` +```javascript JavaScript +Coming Soon +``` + + + +This function will be used to modify the schema of the `LINEAR_CREATE_LINEAR_ISSUE` action, we get rid of the parameters `project_id` and `team_id`, later in the program we will pass these values as inputs to the action manually. The technical term for this is **Action-level Schema Processing**. + +```python Python +def linear_schema_processor(schema: dict) -> dict: + # This way the agent doesn't expect a project and team ID to run the action + del schema['project_id'] + del schema['team_id'] + return schema +``` +```javascript JavaScript +Coming Soon +``` + + +This function will be used to modify the input data for the `LINEAR_CREATE_LINEAR_ISSUE` action. Here we have added the values for `project_id` and `team_id` parameters to the input data. By doing this, we can avoid specifying these values in the prompt and be sure that the agent uses the correct values. The technical term for this is **Action-level Pre-Processing**. + +```python Python +def linear_pre_processor(input_data: dict) -> dict: + input_data['project_id'] = 'e708162b-9b1a-4901-ab93-0f0149f9d805' + input_data['team_id'] = '249ee4cc-7bbb-4ff1-adbe-d3ef2f3df94e' + return input_data +``` +```javascript JavaScript +Coming Soon +``` + + + +This function will be used to modify the output data for the `LINEAR_CREATE_LINEAR_ISSUE` action. Here we are modifying the output to just return the action execution status `successful` & the `issue_id`, by doing this can keep the LLM context clean. The technical term for this is **Action-level Post-Processing**. + +```python Python +def linear_post_processor(output_data: dict) -> dict: + output_data = { + 'success': output_data['successfull'], + 'issue_id': output_data['id'], + } + return output_data +``` +```javascript JavaScript +Coming Soon +``` + + + +When getting tools using the `get_tools()` method, we need to pass the `processors` parameter to specify the schema, pre-processing, and post-processing functions. In this example, we're setting up an Action-level preprocessor by mapping the `LINEAR_CREATE_LINEAR_ISSUE` action to our `linear_schema_processor`, `linear_pre_processor` and `linear_post_processor` functions defined above respectively in schema, pre, and post processors. + + +```python Python {2-12} +tools = composio_toolset.get_tools( + processors={ + "schema": { + Action.LINEAR_CREATE_LINEAR_ISSUE: linear_schema_processor, + }, + "pre": { + Action.LINEAR_CREATE_LINEAR_ISSUE: linear_pre_processor, + }, + "post": { + Action.LINEAR_CREATE_LINEAR_ISSUE: linear_post_processor, + } + }, + actions=[Action.LINEAR_CREATE_LINEAR_ISSUE] +) +``` +```javascript JavaScript +Coming Soon +``` + + + + +```python Python +task = "Create a Linear Issue to update the frontend" + +agent = create_openai_functions_agent(llm, tools, prompt) +agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + +agent_executor.invoke({"input": task}) +``` +```javascript JavaScript +Coming Soon +``` + + + + +### How to use processors at App-level? +Above we saw how to use processors at the Action-level, below is an example of how to use them at the App-level. + +```python Python {2-12} +tools = composio_toolset.get_tools( + processors={ + "pre": { + App.: processor_function, + }, + "post": { + App.: processor_function, + }, + "schema": { + App.: processor_function, + }, + }, + apps=[App.] +) +``` +```javascript JavaScript +Coming Soon +``` + + + + Ensure that your schema processing, preprocessing, and postprocessing functions are efficient and don't introduce significant latency. + diff --git a/docs/patterns/tools/use-tools/use-actions-with-custom-auth.mdx b/docs/patterns/tools/use-tools/use-actions-with-custom-auth.mdx new file mode 100644 index 00000000000..15b834f392d --- /dev/null +++ b/docs/patterns/tools/use-tools/use-actions-with-custom-auth.mdx @@ -0,0 +1,65 @@ +--- +title: "πŸ› οΈ How Can I Use Tools and Actions With Custom Authentication?" +sidebarTitle: "Use Custom Auth" +icon: "lock" +description: "Guide to use Custom Authentication With Tools And Actions" +--- + +### Using Tools and Actions with Custom Auth + +Composio allows you to [execute actions directly](action-guide-without-agents) using custom authentication, in this guide we'll see how to star a repo on GitHub using `GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER` action and passing the **Bearer token** in the headers. You can get the connection paramateters of a connected account like the access token using SDK, learn more [here](../..//Auth/using-connections#fetch-the-connection-parameters) + + + +Use the `add_auth` method to add the custom authentication to the toolset for the app you want to use. `in_` is where you want to add the auth, `name` is the name of the header you want to add and `value` is the value of the header. +```python {7-13} +from composio import ComposioToolSet, App + +toolset = ComposioToolSet() + +toolset.add_auth( + app=App.GITHUB, + parameters=[ + dict( + name="Authorization", + in_="header", + value="Bearer gho_XL9IXXXXXX", + ) + ], +) + +toolset.execute_action( + action="GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER", + params={"owner": "composiohq", "repo": "composio"}, +) +``` + + +Here you need to pass the authentication parameters inside the `authConfig`. `in_` is where you want to add the auth, `name` is the name of the header you want to add and `value` is the value of the header. +```javascript {10-14} +import { OpenAIToolSet } from "composio-core"; + +const toolset = new OpenAIToolSet(); + +const response = await toolset.client.actions.execute({ + actionName: "GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER", + requestBody: { + appName: "github", + authConfig: { + parameters: [{ + name: "Authorization", + in: "header", + value: `Bearer gho_XL9IXXXXXX` + }] + }, + input: { + "owner": "composiohq", + "repo": "composio" + } + } +}); + +console.log(response) +``` + + diff --git a/docs/patterns/tools/use-tools/use-specific-actions.mdx b/docs/patterns/tools/use-tools/use-specific-actions.mdx new file mode 100644 index 00000000000..c65e2ef8c11 --- /dev/null +++ b/docs/patterns/tools/use-tools/use-specific-actions.mdx @@ -0,0 +1,136 @@ +--- +title: "How can I get and use specific actions from a Tool?" +sidebarTitle: "Use Specific Actions" +icon: "pickaxe" +description: "Each Tool (like GitHub, Slack, etc.) comes with many Actions. You can explore all available Tools & Actions [here](https://app.composio.dev/apps). Each Action has an associated action ID which you can use to call the action." +--- + + + Providing too many actions can overwhelm the LLM's decision-making process. It's best to narrow down the action set to only the most relevant ones for your specific use case. + + +### Specifying Actions +`GITHUB_CREATE_AN_ISSUE` and `GITHUB_COMMIT_EVENT` are action IDs for actions in the GitHub Tool + +```python Python +from composio_langchain import ComposioToolSet, Action + +toolset = ComposioToolSet() + +# can pass multiple actions +tools = toolset.get_tools( + actions=[Action.GITHUB_CREATE_AN_ISSUE] +) +``` + +```javascript Javascript +import { LangchainToolSet } from "composio-core"; + +const toolset = new LangchainToolSet(); + +// can pass multiple actions +const tools = await toolset.getTools({actions: ['github_issues_create','github_commit_event']}); +``` + + +### Filtering Actions +Actions can be filtered by tags or use case. + + +Filter the Actions in an App based on tags. +For example, you can: +- Filter all user-related Actions using the "users" tag +- Retrieve metadata-related Actions using the "meta" tag + + +```python Python +from composio_langchain import ComposioToolSet, App +tool_set = ComposioToolSet() + +tools = tool_set.get_tools(apps=[App.GITHUB]) + +# Filter by tags +tag = "users" + +action_enums = tool_set.find_actions_by_tags( + App.GITHUB, + tags=[tag], +) + +tools = tool_set.get_tools(actions=action_enums) +``` + +```javascript Javascript +import { OpenAIToolSet } from "composio-core"; + +const composio_toolset = new OpenAIToolSet(); + +// Filter by tags +const tag = "meta"; + +const actions = await composio_toolset.getTools({ + apps: ["github"], + tags: [tag], +}); + +console.log(actions); +``` + +```bash CLI +composio actions --app 'github' --tag 'code' +``` + + + +Find relevant actions for your use case by describing your use case in natural language. +- Pass the use case as a string to the `use_case` parameter. + +```Python Python +from composio_openai import ComposioToolSet, App + +composio_toolset = ComposioToolSet() + +use_case="Create an issue in Linear & send the issue URL on Slack to a slack channel" + +action_enums=composio_toolset.find_actions_by_use_case(App.GITHUB, use_case=use_case, advanced=False) +tools = composio_toolset.get_tools(actions=action_enums) + +print(tools) +``` + +```Javascript Javascript +import { OpenAIToolSet } from "composio-core"; + +const toolset = new OpenAIToolSet(); + +// -- Normal way -- +// Specify the use case +const useCase = "Star a repo on github"; + +const actionsList = await toolset.client.actions.list({ + useCase: useCase, + apps: "github", +}); + +console.log(actionsList); + + +// -- Advanced way -- +(async() => { + const actionsEnums = await toolset.client.actions.findActionEnumsByUseCase({ + apps: ["github", "gmail"], + useCase: "get repo details and send an email to the owner of the repo" + }); + console.log(actionsEnums); +})(); +``` + +```bash CLI +composio actions --use-case 'star a repo on github' --app 'github' +``` + + +Set the `advanced` flag to `True` to get actions for complex use cases (Python) + + + diff --git a/docs/patterns/tools/use-tools/use-tools-with-your-auth.mdx b/docs/patterns/tools/use-tools/use-tools-with-your-auth.mdx new file mode 100644 index 00000000000..35c6ff08603 --- /dev/null +++ b/docs/patterns/tools/use-tools/use-tools-with-your-auth.mdx @@ -0,0 +1,65 @@ +--- +title: "πŸ› οΈ How Can I Use Tools and Actions With Existing Authentication?" +sidebarTitle: "Use Tools With Your Auth" +icon: "lock" +description: "Guide to using existing authentication with tools and actions" +--- + +### Using Tools and Actions with Existing Authentication + +Composio allows you to [execute actions directly](action-guide-without-agents) using existing authentication, in this guide we'll see how to star a repo on GitHub using `GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER` action and passing the **Bearer token** in the headers. You can get the connection paramateters of a connected account like the access token using SDK, learn more [here](../..//Auth/using-connections#fetch-the-connection-parameters) + + + +Use the `add_auth` method to add the existing authentication to the toolset for the app you want to use. `in_` is where you want to add the auth, `name` is the name of the header you want to add and `value` is the value of the header. +```python {7-13} +from composio import ComposioToolSet, App + +toolset = ComposioToolSet() + +toolset.add_auth( + app=App.GITHUB, + parameters=[ + dict( + name="Authorization", + in_="header", + value="Bearer gho_XL9IXXXXXX", + ) + ], +) + +toolset.execute_action( + action="GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER", + params={"owner": "composiohq", "repo": "composio"}, +) +``` + + +Here you need to pass the authentication parameters inside the `authConfig`. `in_` is where you want to add the auth, `name` is the name of the header you want to add and `value` is the value of the header. +```javascript {10-14} +import { OpenAIToolSet } from "composio-core"; + +const toolset = new OpenAIToolSet(); + +const response = await toolset.client.actions.execute({ + actionName: "GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER", + requestBody: { + appName: "github", + authConfig: { + parameters: [{ + name: "Authorization", + in: "header", + value: `Bearer gho_XL9IXXXXXX` + }] + }, + input: { + "owner": "composiohq", + "repo": "composio" + } + } +}); + +console.log(response) +``` + + diff --git a/docs/patterns/tools/what-are-tools.mdx b/docs/patterns/tools/what-are-tools.mdx new file mode 100644 index 00000000000..2ceac2138eb --- /dev/null +++ b/docs/patterns/tools/what-are-tools.mdx @@ -0,0 +1,79 @@ +--- +title: "πŸ› οΈ What are Tools & Actions?" +sidebarTitle: "What are Tools?" +icon: "question" +description: "Learn about tools in Composio" +--- +### What are tools? + +Large Language Models (LLMs) are like a highly intelligent person who can understand and reason about almost anything but is sitting in an empty room with no ability to interact with the outside world. They can think and talk about sending emails, creating a ticket on Jira, or cloning a repository from GitHub, but can't actually DO these things. + +This is where tools come in. Tools give this intelligent being specific abilities to interact with the real world. Many AI models support tool calling (also called function calling). + + +The term **tools** and **actions** are used interchangeably in the documentation + + +### How tool calling works +AI models with tool calling capabilities decide when and how to use specific tools to meet user requests. Developers create and provide these tools, equipping the AI with a toolbox to select the best tool for each task + +For example, if a user asks an LLM to send an email to `john@example.com` with subject `Meeting Tomorrow`, the LLM can use the [Gmail](https://app.composio.dev/app/gmail) tool's `GMAIL_SEND_EMAIL` action to send the email. + +LLM's thinking process: +1. Recognizes this requires email sending capability +2. Identifies the appropriate tool ([Gmail](https://app.composio.dev/app/gmail)) & action (`GMAIL_SEND_EMAIL`) +3. Structures the necessary parameters: + - recipient: john@example.com + - subject: "Meeting Tomorrow" + - body: [drafts appropriate content] +4. Calls the action with these parameters + + +### Tool calling with Composio + +At Composio, we offer tools for multiple platforms, accessible via Python and JavaScript SDKs. These platforms, referred to as **Apps** or **Tools**, include popular services like GitHub, Twitter, Salesforce, Jira, and Notion. Within each of these Apps, we provide **Actions**, which are essentially functions that can be executed. For example, you can send an email on Gmail, star a repository on GitHub, or create an issue on Jira. These tools can also be used directly, similar to function calls, without needing agents. + + +```python Python +from composio_langchain import ComposioToolSet, Action, App + +tool_set = ComposioToolSet() + +# Get all actions from a tool +tools = tool_set.get_tools(apps=[App.GITHUB]) + +# Get specific actions +tools = tool_set.get_tools(actions=[Action.GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER]) +``` + +```javascript JavaScript +import { LangchainToolSet } from "composio-core"; + +const composioToolset = new LangchainToolSet(); + +// Get all actions from a tool +const tools = await composioToolset.getTools({ apps: ["github"] }); + +// Get specific actions +const tools = await composioToolset.getTools({ actions: ["github_star_a_repository_for_the_authenticated_user"] }); +``` + + +### Action Types + +1. **External Tool Actions**: Pre-configured actions for specific tools, such as creating issues or changing issue status in Jira. +2. **System Management Actions**: Actions that interact with the execution environment, like file system operations, shell commands, and browser automation. +3. **Custom Actions**: User-defined actions in Python or JavaScript that extend Composio's capabilities to interact with new or existing tools. + +### Action Limits + +Empirical evidence indicates that agents perform optimally when limited to **fewer than 20 actions**. Providing LLMs with too many actions can lead to significant performance issues, such as **increased response time** and **decreased accuracy**. + +To optimize agent performance, it's essential to limit the number of actions available. This can be achieved through effective action filtering strategies. Here are some recommended approaches: + +1. Use specific actions from a tool +2. Use tags to filter actions +3. Use use cases to filter actions +4. Implement custom filtering logic + +By carefully curating the action set, you can significantly improve agent efficiency and response quality. diff --git a/docs/patterns/triggers/triggers.mdx b/docs/patterns/triggers/triggers.mdx new file mode 100644 index 00000000000..7f7f4267999 --- /dev/null +++ b/docs/patterns/triggers/triggers.mdx @@ -0,0 +1,196 @@ +--- +title: "Getting Started with Triggers" +sidebarTitle: "Triggers" +icon: "webhook" +description: "Triggers monitor specific events in apps like GitHub or Gmail and notify your agents via webhooks. When triggered, they send relevant data that your agents can act upon" +--- + +## Enabling & Disabling Triggers +You can enable a trigger by specifying the trigger enum, available on the [dashboard](https://app.composio.dev/app/github) + + + + +View the required configuration parameters for enabling a trigger by using the show command. For example, this will display what parameters are needed for Github's new star event trigger: +```Bash +composio triggers show GITHUB_STAR_ADDED_EVENT +``` + + +You need to pass the trigger enum to enable a trigger & you'll be prompted to enter the required parameters. +```Bash +composio triggers enable GITHUB_STAR_ADDED_EVENT +``` + + +You need to pass the trigger id to disable a trigger. You can get the trigger id from logs (when you enable a trigger) or from the dashboard. +```Bash +composio triggers disable 818bd52e-c527-446b-b2b5-7410db9aa607 +``` + + + + + + +```python +from composio import ComposioToolSet, App +``` + + +Triggers require you to pass config parameters, which can be obtained by calling the `get_trigger` method and passing the trigger enum. +```python +toolset = ComposioToolSet() + +trigger_schema = toolset.get_trigger("GITHUB_STAR_ADDED_EVENT") +print(trigger_schema.config) +``` + +Response: +```json +properties={ + 'owner': TriggerConfigPropertyModel(description='Owner of the repository', + title='Owner', + type='string'), + 'repo': TriggerConfigPropertyModel(description='Repository name', + title='Repo', + type='string') +} +title='WebhookConfigSchema' +type='object' +required=[ + 'owner', + 'repo' +] +``` + + +You need to pass the trigger enum and the config parameters to enable a trigger, and **trigger id** will be returned. +You can pass entity id to enable trigger for a specific entity. Learn more about entities [here](../auth/connected_account#entities) +```python {1} +entity = toolset.get_entity() +response = entity.enable_trigger( + app=App.GITHUB, + trigger_name="GITHUB_PULL_REQUEST_EVENT", + config={"owner": "composiohq", "repo": "composio"}, +) +print(response) +``` + + +You need to pass the trigger id to disable a trigger. You can get the trigger id from response (when you enable a trigger) or from the dashboard. +```python +entity.disable_trigger("818bd52e-c527-446b-b2b5-7410db9aa607") +``` + + + + + + +```javascript +import { OpenAIToolSet } from "composio-core"; +const toolset = new OpenAIToolSet(); +``` + + +Triggers have a config schema, which can be obtained by calling the `get_trigger` method and passing the trigger enum. +```javascript +coming soon +``` + + +You need to pass the trigger enum and the config parameters to enable a trigger, and **trigger id** will be returned. +You can pass entity id to enable trigger for a specific entity. Learn more about entities [here](../auth/connected_account#entities) +```javascript {1} +const entity = toolset.client.getEntity(); + +(async () => { + console.log( + "res: ", + await entity.setupTrigger("github", "GITHUB_STAR_ADDED_EVENT", { + owner: "composiohq", + repo: "composio", + }) + ); +})(); +``` + + +You need to pass the trigger id to disable a trigger. You can get the trigger id from response (when you enable a trigger) or from the dashboard. +```javascript +const res = await entity.disableTrigger("f95b3f90-ea09-4ef2-945c-dce50f9c7eeb") +console.log(res) +``` + + + + + +
+