# Overview

An agent gets far more useful once it can reach the tools your team already uses. For instance, your support agent can check GitHub to answer "Is the login bug fixed yet?"

- [Connectors](#connectors): Linear, Slack, GitHub, Sentry and more. One shared account, or each user's own.
- [Your functions](#your-own-functions): Any internal API or database, run in your process.
- [Knowledge sources](#knowledge-and-web-search): Files in the repo and pages the agent keeps itself filled from.
- [Web search](#knowledge-and-web-search): Exa, Tavily and Perplexity behind one search route.
- [Stream Chat and Video](#stream-chat-and-video): Agents join calls and answer in channels natively.
- [Telephony](https://getstream.io/agents/docs/python/telephony/purchase-number/): Twilio and Telnyx numbers, or your own SIP trunk.

## Connectors

Add a connector by its name under `connectors` in `agent.yaml`:

```yaml title="agents/assistant/agent.yaml"
name: assistant # an internal assistant for your team
mode: text
llm: llm-fast
connectors:
  - linear # each user signs in to their own Linear
  - name: github
    connection: company # one account the app owns, by its label
```

```sh
getstream agents test assistant --sync
```

And ask: "What are the open issues in GetStream/awesome-ai-news?"

The model sees each tool as `<name>__<tool>`, for example `linear__list_issues`.

### Whose account

Each connector uses one shared account or each user's own. A public MCP server needs no account:

| Whose account       | In `agent.yaml`                   | Who connects it                                           | Example              | Learn more                                                                   |
| ------------------- | --------------------------------- | --------------------------------------------------------- | -------------------- | ---------------------------------------------------------------------------- |
| Each user's own     | a name, such as `- linear`        | each user, in the dashboard test or on a page of your app | their Linear issues  | [Each user's account](https://getstream.io/agents/docs/python/connectors/each-user-account/) |
| One shared account  | `connection`, a label or an id    | you, once, in the dashboard or from your backend          | the company's GitHub | [Shared account](https://getstream.io/agents/docs/python/connectors/shared-account/)         |
| A public MCP server | your connector, with `connection` | you, once, from your backend                              | DeepWiki             | [Custom connectors](https://getstream.io/agents/docs/python/connectors/mcp/)                 |

Generally we recommend a shared account for company tools like GitHub, so your users never have to sign in. Use each user's own account when the agent should act as that person, for instance to answer "Which Linear issues are assigned to me?"

### Catalog

| Connector         | What the agent can do                                       | Sign-in                                    |
| ----------------- | ----------------------------------------------------------- | ------------------------------------------ |
| `slack`           | Search the workspace, read messages, and look people up     | OAuth, Stream's client only                |
| `github`          | Search repositories, and read issues and pull requests      | OAuth, your client or Stream's; or a token |
| `sentry`          | Search issues and errors, and read their events             | OAuth, registers its own client            |
| `linear`          | Search issues and projects, and read workspace context      | OAuth, registers its own client            |
| `notion`          | Search and read the pages and databases the user can access | OAuth, registers its own client            |
| `hubspot`         | Search contacts, companies and deals                        | OAuth, your client or Stream's             |
| `salesforce`      | Read CRM records                                            | OAuth, your client or Stream's             |
| `calendly`        | Check availability                                          | OAuth, registers its own client            |
| `calcom`          | Read bookings and event types                               | OAuth, registers its own client            |
| `google_calendar` | Read calendars, events and free time                        | OAuth, your client or Stream's             |
| `google_drive`    | Search files and folders, and read what is in them          | OAuth, your client or Stream's             |
| `google_docs`     | Read documents and their contents                           | OAuth, your client or Stream's             |
| `gmail`           | Search email threads, and read drafts                       | OAuth, your client or Stream's             |
| `bigquery`        | List datasets, and run SQL queries                          | OAuth, your client or Stream's             |
| `metabase`        | Search, and browse collections and data                     | OAuth, registers its own client            |
| `gong`            | Look up CRM accounts                                        | OAuth, your client, or registers its own   |
| `shopify`         | Search a shop's policies and FAQs                           | none                                       |

"Registers its own client" means you set up nothing. To use your own client, see [OAuth clients](https://getstream.io/agents/docs/python/connectors/each-user-account/#oauth-clients).

- `github` also takes a personal access token. See [Shared account](https://getstream.io/agents/docs/python/connectors/shared-account/#create-it-from-your-backend).
- `shopify` needs the shop's `myshopify.com` address and no sign-in. See [A shop with no sign-in](https://getstream.io/agents/docs/python/connectors/shared-account/#a-shop-with-no-sign-in).
- `metabase` takes your Metabase's host name as the input `host`, such as `metabase.example.com`. It asks for read and query scopes only, so the tools that write are not offered.
- `gong` needs an integration registered by a Gong technical administrator on a paid seat.

### Channels

Slack, WhatsApp, iMessage and SMS let people talk to the agent, instead of giving it tools. Each one uses a shared account, set with `connection`:

- [Slack](https://getstream.io/agents/docs/python/connectors/slack/): `slack_bot` answers in Slack threads as your workspace's own bot
- [WhatsApp](https://getstream.io/agents/docs/python/connectors/whatsapp/): `whatsapp` answers on WhatsApp with your own Meta app
- [iMessage](https://getstream.io/agents/docs/python/connectors/imessage/): `linq` answers over iMessage on your own Linq line
- [SMS](https://getstream.io/agents/docs/python/connectors/sms/): `telnyx` answers over SMS on your own Telnyx number

## Your own functions

For anything that is not a connector, register a function. The model calls it over the session socket and your process runs it, so it can reach private databases and internal APIs without exposing them:

```ts label="JavaScript"
agent.tools.register<{
  summary: string;
  priority: "low" | "normal" | "urgent";
}>({
  name: "create_ticket",
  description: "Open a support ticket for the caller",
  parameters: {
    type: "object",
    properties: {
      summary: {
        type: "string",
        description: "one sentence describing the problem",
      },
      priority: { type: "string", enum: ["low", "normal", "urgent"] },
    },
    required: ["summary", "priority"],
  },
  run: ({ summary, priority }, signal) =>
    tickets.create(summary, priority, signal),
});
```

```kotlin label="Kotlin"
import kotlinx.serialization.json.jsonPrimitive

val createTicket = AgentTool(
    name = "create_ticket",
    description = "Open a support ticket for the caller",
    parameters = AgentTool.strings(
        mapOf(
            "summary" to "one sentence describing the problem",
            "priority" to "low, normal or urgent",
        ),
        required = listOf("summary", "priority"),
    ),
) { args ->
    tickets.create(
        args["summary"]?.jsonPrimitive?.content.orEmpty(),
        args["priority"]?.jsonPrimitive?.content.orEmpty(),
    )
}

val session = agents.agent("support").chat(createTicket)
```

```swift label="Swift"
let createTicket = AgentTool(
    name: "create_ticket",
    description: "Open a support ticket for the caller",
    parameters: .strings([
        "summary": "one sentence describing the problem",
        "priority": "low, normal or urgent",
    ], required: ["summary", "priority"])
) { arguments in
    try await tickets.create(arguments["summary"]?.stringValue ?? "", arguments["priority"]?.stringValue ?? "")
}

let session = try await agents.chat(agent: "support", tools: [createTicket])
await session.start()
```

```dart label="Dart"
final createTicket = AgentTool(
  name: 'create_ticket',
  description: 'Open a support ticket for the caller',
  parameters: AgentTool.strings({
    'summary': 'one sentence describing the problem',
    'priority': 'low, normal or urgent',
  }, required: ['summary', 'priority']),
  run: (arguments) =>
      tickets.create(arguments['summary'] as String, arguments['priority'] as String),
);

final session = await agents.agent('support').chat(SessionOptions(tools: [createTicket]));
```

```python label="Python"
@agent.llm.register_function(description="Open a support ticket for the caller")
async def create_ticket(summary: str, priority: str) -> dict[str, str]:
    return await tickets.create(summary, priority)
```

```ruby label="Ruby"
agent.tools.register("create_ticket",
                     description: "Open a support ticket for the caller",
                     params: {
                       summary: "one sentence describing the problem",
                       priority: "low, normal or urgent"
                     }) do |summary:, priority:|
  Tickets.create(summary, priority)
end
```

```php label="PHP"
use GetStream\VisionAgents\Describe;

$agent->tools->register(
    'create_ticket',
    'Open a support ticket for the caller',
    fn (
        #[Describe('one sentence describing the problem')] string $summary,
        #[Describe('low, normal or urgent')] string $priority,
    ) => $tickets->create($summary, $priority),
);
```

```go label="Go"
type CreateTicket struct {
	Summary  string `json:"summary" schema:"one sentence describing the problem"`
	Priority string `json:"priority" schema:"low, normal or urgent"`
}

err := tools.Register(agent.Tools(), "create_ticket", "Open a support ticket for the caller",
	func(ctx context.Context, args CreateTicket) (any, error) {
		return tickets.Create(ctx, args.Summary, args.Priority)
	})
```

```csharp label="C#"
agent.Tools.Register<CreateTicket, Ticket>("create_ticket",
    "Open a support ticket for the caller",
    (args, cancellationToken) => tickets.CreateAsync(args.Summary, args.Priority, cancellationToken));

record CreateTicket(
    [property: Description("one sentence describing the problem")] string Summary,
    [property: Description("low, normal or urgent")] string Priority);
```

```rust label="Rust"
use schemars::JsonSchema;
use serde::Deserialize;
use vision_agents::Tools;

#[derive(Deserialize, JsonSchema)]
struct CreateTicket {
    /// one sentence describing the problem
    summary: String,
    /// low, normal or urgent
    priority: String,
}

let tools = Tools::new();
tools.register("create_ticket", "Open a support ticket for the caller", |args: CreateTicket| async move {
    tickets::create(&args.summary, &args.priority).await
});
```

See [Tool calling & Dispatch](https://getstream.io/agents/docs/python/tool-calling-and-dispatch/) for the details.

## Knowledge and web search

- `knowledge/` in the agent folder, and pages in `knowledge/urls.yaml` that we crawl and keep fresh. See [Knowledge & skills](https://getstream.io/agents/docs/python/knowledge-and-skills/).
- `search: search-fast` in `agent.yaml` lets the agent search the web with Exa, Tavily or Perplexity.
- Agents remember people across conversations. See [Memory & Persistence](https://getstream.io/agents/docs/python/memory-and-persistence/).

## Stream Chat and Video

Agents are native to Stream:

- An agent joins a Stream Video call, or holds a written conversation in a Stream Chat channel that outlives the session.
- [Dispatch](https://getstream.io/agents/docs/python/tool-calling-and-dispatch/#dispatch) answers messages written to an agent's channel and calls that reach Stream over SIP.
- Your apps join the same call or channel with the client SDKs.

## Webhooks

- A guardrail webhook lets your server decide which turns the agent answers. See [Guardrails](https://getstream.io/agents/docs/python/guardrails/#webhook-guardrail-example).
- A transcription job with a callback URL calls you when the transcript is ready.

## Connectors deep dive

Each entry under `connectors` takes these keys:

| Key          | What it sets                                                                                                                        | Default                       |
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- |
| `name`       | The name the model sees each tool under, as `<name>__<tool>`                                                                        | Required                      |
| `connector`  | The connector id, such as `linear` or `custom_wiki`                                                                                 | `name`                        |
| `connection` | One account the app owns, by its id or label. See [Whose account](#whose-account)                                                   | Each user's own account       |
| `tools`      | Tool names or patterns to offer. See [Choosing tools](https://getstream.io/agents/docs/python/connectors/choosing-tools/)                           | Every tool                    |
| `required`   | `true` refuses a session whose connection is missing or not connected                                                               | Optional: the session goes on |
| `sandbox`    | `true` lets code in the agent's sandbox call the connector's API. See [Sandbox access](https://getstream.io/agents/docs/python/connectors/sandbox/) | No access                     |

A name alone, such as `- linear`, is the same as `name: linear`.

When the agent syncs, a `connection` the app doesn't have is left out with a warning, and the rest of the agent syncs. With `required: true`, the sync fails instead. Leaving `connectors` out of `agent.yaml` keeps what is already stored, and an empty list removes it.

### Going further

- [Each user's account](https://getstream.io/agents/docs/python/connectors/each-user-account/): Let each user sign in, from the dashboard or your own app.
- [Shared account](https://getstream.io/agents/docs/python/connectors/shared-account/): One account the app owns, for every conversation.
- [Custom connectors](https://getstream.io/agents/docs/python/connectors/mcp/): Any MCP server: public, behind a key, or with a sign-in.
- [Choosing tools](https://getstream.io/agents/docs/python/connectors/choosing-tools/): Offer only the tools the agent needs.
- [Slack](https://getstream.io/agents/docs/python/connectors/slack/): Answer in Slack threads as your workspace's bot.
- [WhatsApp](https://getstream.io/agents/docs/python/connectors/whatsapp/): Answer on WhatsApp with your own Meta app.
- [iMessage](https://getstream.io/agents/docs/python/connectors/imessage/): Answer over iMessage on your own Linq line.
- [SMS](https://getstream.io/agents/docs/python/connectors/sms/): Answer over SMS on your own Telnyx number.
- [Sandbox access](https://getstream.io/agents/docs/python/connectors/sandbox/): Let code in the agent's sandbox call a connector's API.
- [Troubleshooting](https://getstream.io/agents/docs/python/connectors/troubleshooting/): Errors you may see, why, and what to do.

---

For the most recent version of this documentation, visit [https://getstream.io/agents/docs/python/connectors/](https://getstream.io/agents/docs/python/connectors/).