Let your agent prompt users to connect accounts during conversation
In-chat authentication lets your agent prompt users to connect accounts during chat. When a tool requires authentication, the agent returns a Connect Link URL. The user authenticates, confirms in chat, and the agent retries.
By just creating a session with default configs, you are enabling in-chat auth. The manage_connections parameter defaults to True, which includes the COMPOSIO_MANAGE_CONNECTIONS meta-tool automatically:
@paramuserId The user id to create the session for@paramconfig The config for the tool router session@returnsThe tool router session@example```typescript
import { Composio } from '@composio/core';
const composio = new Composio();
const userId = 'user_123';
const session = await composio.create(userId, {
manageConnections: true,
});
console.log(session.sessionId);
console.log(session.url);
console.log(session.tools());
```
@paramuserId The user id to create the session for@paramconfig The config for the tool router session@returnsThe tool router session@example```typescript
import { Composio } from '@composio/core';
const composio = new Composio();
const userId = 'user_123';
const session = await composio.create(userId, {
manageConnections: true,
});
console.log(session.sessionId);
console.log(session.url);
console.log(session.tools());
```
from dotenv import load_dotenvfrom composio import Composiofrom agents import Agent, Runner, SQLiteSessionfrom composio_openai_agents import OpenAIAgentsProviderload_dotenv()# Initialize Composio with OpenAI Agents provider (API key from env var COMPOSIO_API_KEY)composio = Composio(provider=OpenAIAgentsProvider())# Unique identifier of the useruser_id = "user_123"# Create a session and get native tools for the usersession = composio.create(user_id=user_id)tools = session.tools()# Configure OpenAI agent with Composio toolsagent = Agent( name="Personal Assistant", instructions="You are a helpful personal assistant. Use Composio tools to take action.", model="gpt-5.2", tools=tools,)# Memory for multi-turn conversationmemory = SQLiteSession("conversation")print("""What task would you like me to help you with?I can use tools like Gmail, GitHub, Linear, Notion, and more.(Type 'exit' to exit)Example tasks: • 'Summarize my emails from today' • 'List all open issues on the composio github repository'""")while True: user_input = input("You: ").strip() if user_input.lower() == "exit": break print("Assistant: ", end="", flush=True) try: result = Runner.run_sync(starting_agent=agent, input=user_input, session=memory) print(f"{result.final_output}\n") except Exception as e: print(f"\n[Error]: {e}")
This is the core class for Composio.
It is used to initialize the Composio SDK and provide a global configuration.
Composio } from "@composio/core";import { class Agent<TContext = unknown, TOutput extends AgentOutputType = "text">
The class representing an AI agent configured with instructions, tools, guardrails, handoffs and more.
We strongly recommend passing `instructions`, which is the "system prompt" for the agent. In
addition, you can pass `handoffDescription`, which is a human-readable description of the
agent, used when the agent is used inside tools/handoffs.
Agents are generic on the context type. The context is a (mutable) object you create. It is
passed to tool functions, handoffs, guardrails, etc.
Executes an agent workflow with the shared default `Runner` instance.
@paramagent - The entry agent to invoke.@paraminput - A string utterance, structured input items, or a resumed `RunState`.@paramoptions - Controls streaming mode, context, session handling, and turn limits.@returnsA `RunResult` when `stream` is false, otherwise a `StreamedRunResult`.
run, class MemorySession
Simple in-memory session store intended for demos or tests. Not recommended for production use.
MemorySession } from "@openai/agents";import { class OpenAIAgentsProviderOpenAIAgentsProvider } from "@composio/openai-agents";import { function createInterface(input: NodeJS.ReadableStream, output?: NodeJS.WritableStream, completer?: Completer, terminal?: boolean): Interface (+1 overload)
The `readlinePromises.createInterface()` method creates a new `readlinePromises.Interface` instance.
```js
import readlinePromises from 'node:readline/promises';
const rl = readlinePromises.createInterface({
input: process.stdin,
output: process.stdout,
});
```
Once the `readlinePromises.Interface` instance is created, the most common case
is to listen for the `'line'` event:
```js
rl.on('line', (line) => {
console.log(`Received: ${line}`);
});
```
If `terminal` is `true` for this instance then the `output` stream will get
the best compatibility if it defines an `output.columns` property and emits
a `'resize'` event on the `output` if or when the columns ever change
(`process.stdout` does this automatically when it is a TTY).
@sincev17.0.0
createInterface } from "readline/promises";// Initialize Composio with OpenAI Agents provider (API key from env var COMPOSIO_API_KEY)constconst composio: Composio<OpenAIAgentsProvider>composio = newnew Composio<OpenAIAgentsProvider>(config?: ComposioConfig<OpenAIAgentsProvider> | undefined): Composio<OpenAIAgentsProvider>
Creates a new instance of the Composio SDK.
The constructor initializes the SDK with the provided configuration options,
sets up the API client, and initializes all core models (tools, toolkits, etc.).
@paramconfig - Configuration options for the Composio SDK@paramconfig.apiKey - The API key for authenticating with the Composio API@paramconfig.baseURL - The base URL for the Composio API (defaults to production URL)@paramconfig.allowTracking - Whether to allow anonymous usage analytics@paramconfig.provider - The provider to use for this Composio instance (defaults to OpenAIProvider)@example```typescript
// Initialize with default configuration
const composio = new Composio();
// Initialize with custom API key and base URL
const composio = new Composio({
apiKey: 'your-api-key',
baseURL: 'https://api.composio.dev'
});
// Initialize with custom provider
const composio = new Composio({
apiKey: 'your-api-key',
provider: new CustomProvider()
});
```
The tool provider to use for this Composio instance.
@examplenew OpenAIProvider()
provider: new
new OpenAIAgentsProvider(options?: { strict?: boolean;}): OpenAIAgentsProvider
Creates a new instance of the OpenAIAgentsProvider.
This provider enables integration with the
@openai/agents package,
allowing Composio tools to be used with OpenAI Agents.@example```typescript
// Initialize the OpenAIAgentsProvider
const provider = new OpenAIAgentsProvider();
// Use with Composio
const composio = new Composio({
apiKey: 'your-api-key',
provider: new OpenAIAgentsProvider()
});
// Use the provider to wrap tools for@openai/agents
const agentTools = provider.wrapTools(composioTools, composio.tools.execute);
```
OpenAIAgentsProvider() });// Unique identifier of the userconstconst userId: "user_123"userId = "user_123";// Create a tool router session for the userconstconst session: ToolRouterSession<unknown, unknown, OpenAIAgentsProvider>session = awaitconst composio: Composio<OpenAIAgentsProvider>composio.Composio<OpenAIAgentsProvider>.create: (userId: string, routerConfig?: ToolRouterCreateSessionConfig) => Promise<ToolRouterSession<unknown, unknown, OpenAIAgentsProvider>>
Creates a new tool router session for a user.
@paramuserId The user id to create the session for@paramconfig The config for the tool router session@returnsThe tool router session@example```typescript
import { Composio } from '@composio/core';
const composio = new Composio();
const userId = 'user_123';
const session = await composio.create(userId, {
manageConnections: true,
});
console.log(session.sessionId);
console.log(session.url);
console.log(session.tools());
```
The class representing an AI agent configured with instructions, tools, guardrails, handoffs and more.
We strongly recommend passing `instructions`, which is the "system prompt" for the agent. In
addition, you can pass `handoffDescription`, which is a human-readable description of the
agent, used when the agent is used inside tools/handoffs.
Agents are generic on the context type. The context is a (mutable) object you create. It is
passed to tool functions, handoffs, guardrails, etc.
The instructions for the agent. Will be used as the "system prompt" when this agent is
invoked. Describes what the agent should do, and how it responds.
Can either be a string, or a function that dynamically generates instructions for the agent.
If you provide a function, it will be called with the context and the agent instance. It
must return a string.
instructions: "You are a helpful personal assistant. Use Composio tools to take action.",model?: string | Model | undefined
The model implementation to use when invoking the LLM.
By default, if not set, the agent will use the default model returned by
getDefaultModel (currently "gpt-4.1").
tools,});// Set up interactive terminal input/output for the conversationconstconst readline: Interfacereadline =function createInterface(options: ReadLineOptions): Interface (+1 overload)
The `readlinePromises.createInterface()` method creates a new `readlinePromises.Interface` instance.
```js
import readlinePromises from 'node:readline/promises';
const rl = readlinePromises.createInterface({
input: process.stdin,
output: process.stdout,
});
```
Once the `readlinePromises.Interface` instance is created, the most common case
is to listen for the `'line'` event:
```js
rl.on('line', (line) => {
console.log(`Received: ${line}`);
});
```
If `terminal` is `true` for this instance then the `output` stream will get
the best compatibility if it defines an `output.columns` property and emits
a `'resize'` event on the `output` if or when the columns ever change
(`process.stdout` does this automatically when it is a TTY).
@sincev17.0.0
createInterface({ input: NodeJS.ReadableStream
The [`Readable`](https://nodejs.org/docs/latest-v24.x/api/stream.html#readable-streams) stream to listen to
The `process.stdin` property returns a stream connected to`stdin` (fd `0`). It is a `net.Socket` (which is a `Duplex` stream) unless fd `0` refers to a file, in which case it is
a `Readable` stream.
For details of how to read from `stdin` see `readable.read()`.
As a `Duplex` stream, `process.stdin` can also be used in "old" mode that
is compatible with scripts written for Node.js prior to v0.10\.
For more information see `Stream compatibility`.
In "old" streams mode the `stdin` stream is paused by default, so one
must call `process.stdin.resume()` to read from it. Note also that calling `process.stdin.resume()` itself would switch stream to "old" mode.
stdin, output?: NodeJS.WritableStream | undefined
The [`Writable`](https://nodejs.org/docs/latest-v24.x/api/stream.html#writable-streams) stream to write readline data to.
The `process.stdout` property returns a stream connected to`stdout` (fd `1`). It is a `net.Socket` (which is a `Duplex` stream) unless fd `1` refers to a file, in which case it is
a `Writable` stream.
For example, to copy `process.stdin` to `process.stdout`:
```js
import { stdin, stdout } from 'node:process';
stdin.pipe(stdout);
```
`process.stdout` differs from other Node.js streams in important ways. See `note on process I/O` for more information.
stdout });// Create a memory session for persistent multi-turn conversationconstconst memory: MemorySessionmemory = newnew MemorySession(options?: MemorySessionOptions): MemorySession
Simple in-memory session store intended for demos or tests. Not recommended for production use.
MemorySession();var console: Console
The `console` module provides a simple debugging console that is similar to the
JavaScript console mechanism provided by web browsers.
The module exports two specific components:
* A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream.
* A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstdout) and
[`process.stderr`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module.
_**Warning**_: The global console object's methods are neither consistently
synchronous like the browser APIs they resemble, nor are they consistently
asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v24.x/api/process.html#a-note-on-process-io) for
more information.
Example using the global `console`:
```js
console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr
```
Example using the `Console` class:
```js
const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
```
Prints to `stdout` with newline. Multiple arguments can be passed, with the
first used as the primary message and all additional used as substitution
values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html)
(the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args)).
```js
const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout
```
See [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
log(`What task would you like me to help you with?I can use tools like Gmail, GitHub, Linear, Notion, and more.(Type 'exit' to exit)Example tasks: • 'Summarize my emails from today' • 'List all open issues on the composio github repository and create a Google Sheet with the issues'`);// Multi-turn conversation with agentic tool callingwhile (true) { constconst query: stringquery = awaitconst readline: Interfacereadline.Interface.question(query: string): Promise<string> (+1 overload)
The `rl.question()` method displays the `query` by writing it to the `output`,
waits for user input to be provided on `input`, then invokes the `callback` function passing the provided input as the first argument.
When called, `rl.question()` will resume the `input` stream if it has been
paused.
If the `Interface` was created with `output` set to `null` or `undefined` the `query` is not written.
If the question is called after `rl.close()`, it returns a rejected promise.
Example usage:
```js
const answer = await rl.question('What is your favorite food? ');
console.log(`Oh, so your favorite food is ${answer}`);
```
Using an `AbortSignal` to cancel a question.
```js
const signal = AbortSignal.timeout(10_000);
signal.addEventListener('abort', () => {
console.log('The food question timed out');
}, { once: true });
const answer = await rl.question('What is your favorite food? ', { signal });
console.log(`Oh, so your favorite food is ${answer}`);
```
@sincev17.0.0@paramquery A statement or query to write to `output`, prepended to the prompt.@returnA promise that is fulfilled with the user's input in response to the `query`.
The `process.stdout` property returns a stream connected to`stdout` (fd `1`). It is a `net.Socket` (which is a `Duplex` stream) unless fd `1` refers to a file, in which case it is
a `Writable` stream.
For example, to copy `process.stdin` to `process.stdout`:
```js
import { stdin, stdout } from 'node:process';
stdin.pipe(stdout);
```
`process.stdout` differs from other Node.js streams in important ways. See `note on process I/O` for more information.
Sends data on the socket. The second parameter specifies the encoding in the
case of a string. It defaults to UTF8 encoding.
Returns `true` if the entire data was flushed successfully to the kernel
buffer. Returns `false` if all or part of the data was queued in user memory.`'drain'` will be emitted when the buffer is again free.
The optional `callback` parameter will be executed when the data is finally
written out, which may not be immediately.
See `Writable` stream `write()` method for more
information.
@sincev0.1.90@paramencoding Only used when data is `string`.
Executes an agent workflow with the shared default `Runner` instance.
@paramagent - The entry agent to invoke.@paraminput - A string utterance, structured input items, or a resumed `RunState`.@paramoptions - Controls streaming mode, context, session handling, and turn limits.@returnsA `RunResult` when `stream` is false, otherwise a `StreamedRunResult`.
The `process.stdout` property returns a stream connected to`stdout` (fd `1`). It is a `net.Socket` (which is a `Duplex` stream) unless fd `1` refers to a file, in which case it is
a `Writable` stream.
For example, to copy `process.stdin` to `process.stdout`:
```js
import { stdin, stdout } from 'node:process';
stdin.pipe(stdout);
```
`process.stdout` differs from other Node.js streams in important ways. See `note on process I/O` for more information.
Sends data on the socket. The second parameter specifies the encoding in the
case of a string. It defaults to UTF8 encoding.
Returns `true` if the entire data was flushed successfully to the kernel
buffer. Returns `false` if all or part of the data was queued in user memory.`'drain'` will be emitted when the buffer is again free.
The optional `callback` parameter will be executed when the data is finally
written out, which may not be immediately.
See `Writable` stream `write()` method for more
information.
@sincev0.1.90@paramencoding Only used when data is `string`.
The final output of the agent. If the output type was set to anything other than `text`,
this will be parsed either as JSON or using the Zod schema you provided.
The `console` module provides a simple debugging console that is similar to the
JavaScript console mechanism provided by web browsers.
The module exports two specific components:
* A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream.
* A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstdout) and
[`process.stderr`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module.
_**Warning**_: The global console object's methods are neither consistently
synchronous like the browser APIs they resemble, nor are they consistently
asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v24.x/api/process.html#a-note-on-process-io) for
more information.
Example using the global `console`:
```js
console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr
```
Example using the `Console` class:
```js
const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
```
Prints to `stderr` with newline. Multiple arguments can be passed, with the
first used as the primary message and all additional used as substitution
values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html)
(the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args)).
```js
const code = 5;
console.error('error #%d', code);
// Prints: error #5, to stderr
console.error('error', code);
// Prints: error 5, to stderr
```
If formatting elements (e.g. `%d`) are not found in the first string then
[`util.inspect()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilinspectobject-options) is called on each argument and the
resulting string values are concatenated. See [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args)
for more information.
The `rl.close()` method closes the `Interface` instance and
relinquishes control over the `input` and `output` streams. When called,
the `'close'` event will be emitted.
Calling `rl.close()` does not immediately stop other events (including `'line'`)
from being emitted by the `Interface` instance.
@sincev0.1.98
close();
What this looks like when you run the code:
Assistant: What would you like me to do today? Type 'exit' to end the conversation.> Star the composio repo on GitHubAssistant: I need you to connect your GitHub account first.Please click here to authorize: https://connect.composio.dev/link/ln_abc123> Done