Skip to content

Commit

Permalink
Merge branch 'master' into ENG-3203
Browse files Browse the repository at this point in the history
  • Loading branch information
Devanshusisodiya authored Feb 12, 2025
2 parents fefebc2 + ef3f79b commit 301a07d
Show file tree
Hide file tree
Showing 34 changed files with 786 additions and 217 deletions.
110 changes: 88 additions & 22 deletions docs/framework/letta.mdx
Original file line number Diff line number Diff line change
@@ -1,29 +1,42 @@
---
title: "Using Composio With Letta"
sidebarTitle: "Letta"
description: "Integrate Composio with Letta to let them seamlessly interact with external apps"
description: "Integrate Composio with Letta agents to let them seamlessly interact with external apps"
---

## Star A Repository on GitHub
In this example, we will use Letta Agent to star a repository on GitHub using Composio Tools

<Steps>
<Step title="Install Packages">
<CodeGroup>
```bash Python
pip install composio_langchain letta
pip install letta-client composio_langchain
```
```bash JavaScript
npm i composio-core @letta-ai/letta-client
```
</CodeGroup>
</Step>
<Step title="Import Libraries & Configure Client">
```bash Python
from letta import EmbeddingConfig, LLMConfig, create_client
from composio_langchain import Action, ComposioToolSet
<CodeGroup>
```python Python
from letta_client import Letta
from composio_langchain import Action, ComposioToolSet, App

client = create_client()
client = Letta(base_url="http://localhost:8283")
```
```javascript JavaScript
import { LettaClient } from '@letta-ai/letta-client'
import { ComposioToolSet } from "composio-core"

# set automatic defaults for LLM/embedding config
client.set_default_llm_config(LLMConfig.default_config(model_name="gpt-4"))
client.set_default_embedding_config(EmbeddingConfig.default_config(model_name="text-embedding-ada-002"))
const client = new LettaClient({
baseUrl: "http://localhost:8283",
});

const toolset = new ComposioToolSet()
```
</CodeGroup>
</Step>

<Step title="Connect Your GitHub Account">
Expand All @@ -38,30 +51,83 @@ toolset = ComposioToolSet()
request = toolset.initiate_connection(app=App.GITHUB)
print(f"Open this URL to authenticate: {request.redirectUrl}")
```
```javascript JavaScript
const connection = await toolset.connectedAccounts.initiate({appName: "github"})
console.log(`Open this URL to authenticate: ${connection.redirectUrl}`);
```
</CodeGroup>
<Tip>
Don't forget to set your `COMPOSIO_API_KEY` and `OPENAI_API_KEY` in your environment variables.
</Tip>
</Step>

<Step title="Add GitHub action to Client">
You can get all the tools for a given app or specific actions as shown below. Learn more [here](../../patterns/tools/use-tools/use-specific-actions)
Adding tools to the client
<CodeGroup>
```python Python
composio_tool = client.load_composio_tool(Action.GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER)
agent_state = client.create_agent()
client.add_tool_to_agent(
agent_id=agent_state.id,
tool_id=composio_tool.id
tool = client.tools.add_composio_tool(composio_action_name=Action.GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER.name)
```
```javascript JavaScript
const tool = await client.tools.addComposioTool(
"GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER",
)
```
</CodeGroup>

</Step>
<Step title="Create the agent">
<CodeGroup>
```python Python
agent = client.agents.create(
name="GitHub Agent",
memory_blocks=[
{"label": "persona", "value": "I am a helpful assistant"}
],
model="openai/gpt-4o",
embedding="openai/text-embedding-ada-002",
tool_ids=[tool.id]
)
```
```javascript JavaScript
const agent = await client.agents.create({
name: "GitHub Agent",
memoryBlocks: [
{
value: "I am a helpful assistant",
label: "persona",
},
],
model: "openai/gpt-4o",
embedding: "openai/text-embedding-ada-002",
toolIds: [tool.id],
});
```
</CodeGroup>
</Step>
<Step title="Execute the Agent">
<CodeGroup>
```python Python
response = client.send_message(agent_id=agent_state.id, role="user", message="Star the repo composiohq/composio")
print(response)
response = client.agents.messages.create(
agent_id=agent.id,
messages=[
{
"role": "user",
"content": "Star the github repo composioHQ/composio/"
}
]
)
for message in response.messages:
print(message)
```
```javascript JavaScript
const response = await client.agents.messages.create(agent.id, {
messages: [
{
role: "user",
content: "Star the github repo composiohq/composio",
},
],
});

for (const message of response.messages) {
console.log(message);
}
```
</CodeGroup>
</Step>
</Steps>
3 changes: 2 additions & 1 deletion docs/mint.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@
]
},
"patterns/tools/custom-integration",
"patterns/tools/serve-tools"
"patterns/tools/serve-tools",
"patterns/tools/versioning"
]
},
{
Expand Down
56 changes: 56 additions & 0 deletions docs/patterns/tools/versioning.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
title: "Action Versioning"
sidebarTitle: "Action Versioning"
description: "Learn how to use versioned actions in Composio"
---

Composio supports semantic versioning for actions to ensure stable and consistent interfaces. This guide explains how version specifiers work and how to use them in your applications.

## Versioning Policies

Composio follows semantic versioning principles:

- **Minor Version Changes** (0_1 → 0_2)
- Non-breaking interface changes
- Examples: Adding optional parameters, extending functionality
- Backward compatible with previous minor versions

- **Major Version Changes** (0_3 → 1_0)
- Breaking interface changes
- Examples: Action deprecation or replacement, Changes in required parameters, Changes in parameter types or formats
- May require updates to existing code

## Version Specifiers

Composio provides several ways to specify which version of an action you want to use:

- `latest` - Uses the most recent version available. For example, if an action has versions 0_1, 0_2, 0_3, 1_0, and 1_1, `latest` will resolve to `1_1`.
- `latest:base` - Uses the latest version before a major version change. Using the same example versions, `latest:base` would resolve to `0_3`.
- `x_y` - Explicitly specify major (x) and minor (y) versions, like `0_1` or `1_0`.

## Using Versions in Code

Here's how to specify versions when using Composio:

<CodeGroup>
```python Python {7,10,13}
from composio_langchain import ComposioToolSet, Action

# Initialize toolset
toolset = ComposioToolSet()

# Use latest base version (default)
tools = toolset.get_tools(actions=[Action.GITHUB_META_ROOT @ "latest:base"])

# Use latest version
tools = toolset.get_tools(actions=[Action.GITHUB_META_ROOT @ "latest"])

# Use specific version
tools = toolset.get_tools(actions=[Action.GITHUB_META_ROOT @ "0_1"])
```
``` javascript JavaScript
coming soon!
```
</CodeGroup>

<Info>If no version is specified it defaults to `latest:base`</Info>
1 change: 1 addition & 0 deletions js/Testing.MD
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ The test suite is designed to run across multiple environments. Before running t
- GitHub integration is enabled and active
- Gmail integration is enabled and active
- CodeInterpreter is configured for the default entity
- Github drive and file_id is configured for the default entity

3. Trigger Configuration
- At least one trigger must be active in the system
Expand Down
3 changes: 3 additions & 0 deletions js/config/getTestConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ const CURRENT_FILE_DIR = __dirname;
export type BACKEND_CONFIG = {
COMPOSIO_API_KEY: string;
BACKEND_HERMES_URL: string;
drive: {
downloadable_file_id: string;
}
}

export const getTestConfig = (): BACKEND_CONFIG => {
Expand Down
5 changes: 4 additions & 1 deletion js/config/test.config.local.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"COMPOSIO_API_KEY": "",
"BACKEND_HERMES_URL": "http://localhost:9900"
"BACKEND_HERMES_URL": "http://localhost:9900",
"drive":{
"downloadable_file_id":"18rcI9N7cJRG15E2qyWXtNSFeDg4Rj-T3"
}
}
5 changes: 4 additions & 1 deletion js/config/test.config.prod.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"COMPOSIO_API_KEY": "pv7s0lpq7z5vu27cikyls",
"BACKEND_HERMES_URL": "https://backend.composio.dev"
"BACKEND_HERMES_URL": "https://backend.composio.dev",
"drive":{
"downloadable_file_id":"18rcI9N7cJRG15E2qyWXtNSFeDg4Rj-T3"
}
}
5 changes: 4 additions & 1 deletion js/config/test.config.staging.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"COMPOSIO_API_KEY": "gxpf3a5v864651jp741heq",
"BACKEND_HERMES_URL": "https://staging-backend.composio.dev"
"BACKEND_HERMES_URL": "https://staging-backend.composio.dev",
"drive":{
"downloadable_file_id":"1K23Tyfb35lpu_syfdsx1w6UfIJ9DRgwq"
}
}
2 changes: 1 addition & 1 deletion js/openapi-ts.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { defineConfig } from "@hey-api/openapi-ts";

export default defineConfig({
client: "@hey-api/client-axios",
input: "http://localhost:9900/openapi.json",
input: "https://backend.composio.dev/openapi.json",
output: "src/sdk/client",
services: {
asClass: true,
Expand Down
19 changes: 17 additions & 2 deletions js/src/sdk/base.toolset.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,16 +160,17 @@ describe("ComposioToolSet class tests", () => {
const ACTION_NAME = "GMAIL_SEND_EMAIL";
const actions = await toolset.getToolsSchema({ actions: [ACTION_NAME] });

const firstAction = actions[0]!;
// Check if exist
expect(
actions[0]!.parameters.properties["attachment_file_uri_path"]
firstAction.parameters.properties["attachment_schema_parsed_file"]
).toBeDefined();

const requestBody = {
recipient_email: "himanshu@composio.dev",
subject: "Test email from himanshu",
body: "This is a test email",
attachment_file_uri_path:
attachment_schema_parsed_file:
"https://composio.dev/wp-content/uploads/2024/07/Composio-Logo.webp",
};

Expand All @@ -184,6 +185,20 @@ describe("ComposioToolSet class tests", () => {
expect(executionResult.data).toBeDefined();
});

it("should execute downloadable file action", async () => {
const ACTION_NAME = "GOOGLEDRIVE_PARSE_FILE";
const executionResult = await toolset.executeAction({
action: ACTION_NAME,
params: {
file_id: testConfig.drive.downloadable_file_id,
},
entityId: "default",
});

// @ts-ignore
expect(executionResult.data.file.uri.length).toBeGreaterThan(0);
});

it("should get tools with usecase limit", async () => {
const tools = await toolset.getToolsSchema({
useCase: "follow user",
Expand Down
Loading

0 comments on commit 301a07d

Please sign in to comment.