> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stackone.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Basic Usage

> Learn the fundamentals of using the StackOne TypeScript SDK for AI agents

## Quick Start

The most common pattern: create a toolset and give your agent search and execute tools. The agent discovers and runs tools on demand.

```typescript theme={null}
import { StackOneToolSet } from "@stackone/ai";

// getTools returns the tool_search + tool_execute meta tools, so search must be
// enabled on the toolset (pass search: {} for defaults).
const toolset = new StackOneToolSet({ search: { method: "auto" } });

// Your agent gets 2 tools: tool_search + tool_execute
const tools = toolset.getTools({ accountIds: ["your-account-id"] });
const openaiTools = tools.toOpenAI();
```

Pass `openaiTools` to any OpenAI-compatible model and the agent will search for relevant tools, then execute them automatically. See the [OpenAI integration guide](/agents/typescript/frameworks/openai-integration) for a full agent loop.

## Fetch Tools

When you need specific tools instead of search and execute:

```typescript theme={null}
const tools = await toolset.fetchTools({ accountIds: ["your-account-id"] });
const openaiTools = tools.toOpenAI();
```

<AccordionGroup>
  <Accordion title="Filtering by provider, action, or pattern">
    ```typescript theme={null}
    // Filter by providers
    const byProviders = await toolset.fetchTools({
      providers: ["hibob", "workday"],
      accountIds: ["your-account-id"],
    });

    // Filter by actions with exact match
    const byActions = await toolset.fetchTools({
      actions: ["hibob_list_employees", "hibob_create_employees"],
      accountIds: ["your-account-id"],
    });

    // Filter by actions with glob patterns
    const byGlob = await toolset.fetchTools({
      actions: ["*_list_*"],
      accountIds: ["your-account-id"],
    });

    // Combine multiple filters
    const combined = await toolset.fetchTools({
      providers: ["hibob"],
      actions: ["*_list_*"],
      accountIds: ["your-account-id"],
    });
    ```

    See [Tool Filtering](/agents/typescript/tool-filtering) for the full reference.
  </Accordion>

  <Accordion title="Multi-account usage">
    ```typescript theme={null}
    // Set accounts on the toolset for all subsequent calls
    toolset.setAccounts(["account-123", "account-456"]);
    const tools = await toolset.fetchTools();

    // Or pass account IDs per request
    const toolsDirect = await toolset.fetchTools({
      accountIds: ["account-123", "account-456"],
    });

    // Loop over customer accounts dynamically
    const customerAccounts = ["account-1", "account-2", "account-3"];

    for (const accountId of customerAccounts) {
      const tools = await toolset.fetchTools({
        actions: ["workday_list_workers"],
        accountIds: [accountId],
      });
      const employeeTool = tools.getTool("workday_list_workers");
      if (employeeTool) {
        const employees = await employeeTool.execute({});
        console.log(`Found employees for ${accountId}`);
      }
    }
    ```
  </Accordion>
</AccordionGroup>

## Tool Execution

<AccordionGroup>
  <Accordion title="Direct tool execution (for debugging)">
    Direct execution is useful for testing and debugging. In production, your agent framework handles tool calls automatically.

    ```typescript theme={null}
    const tools = await toolset.fetchTools({ accountIds: ["your-account-id"] });
    const employeeTool = tools.getTool("workday_list_workers");

    if (employeeTool) {
      const result = await employeeTool.execute({
        query: { limit: 10 },
      });
      console.log(result);
    }
    ```
  </Accordion>

  <Accordion title="File downloads (binary responses)">
    Actions that download a file (for example `googledrive_unified_download_file`, `documents_download_file`, or any `*_unified_download_file`) return raw bytes plus metadata, not parsed JSON. The SDK decides from the response `Content-Type`: JSON is parsed as usual, and anything else is treated as a file download. Because `execute()` is typed to return a JSON object, use the exported `isBinaryDownloadResult` guard to narrow the result to the file shape.

    ```typescript theme={null}
    import { writeFileSync } from "node:fs";
    import { isBinaryDownloadResult } from "@stackone/ai";

    const tools = await toolset.fetchTools({
      actions: ["googledrive_*"],
      accountIds: ["your-account-id"],
    });
    const download = tools.getTool("googledrive_unified_download_file");

    if (download) {
      const result = await download.execute({ id: "file-id" });

      // isBinaryDownloadResult narrows result so content is a Buffer (no cast) and
      // confirms this was a file download rather than a JSON response.
      if (isBinaryDownloadResult(result)) {
        writeFileSync(result.fileName ?? "download.bin", result.content);
      }
    }
    ```

    The narrowed `result` describes the file:

    | Key           | Type             | Description                                                                    |
    | ------------- | ---------------- | ------------------------------------------------------------------------------ |
    | `content`     | `Buffer`         | Raw file bytes. Not JSON-serializable (see note).                              |
    | `contentType` | `string`         | File MIME type (for example `application/pdf`), or `application/octet-stream`. |
    | `statusCode`  | `number`         | HTTP status of the download response.                                          |
    | `headers`     | `object`         | Response headers.                                                              |
    | `fileName`    | `string \| null` | Filename from `Content-Disposition` (RFC 5987 `filename*` aware), else `null`. |

    <Warning>
      `content` is a `Buffer` and is not JSON-serializable. If you forward tool results to an LLM (or anything that re-serializes to JSON), handle or strip the `content` key. For example, base64-encode it on the LLM-facing path.
    </Warning>
  </Accordion>
</AccordionGroup>

## Environment Configuration

```bash theme={null}
export STACKONE_API_KEY=your_api_key
```

Account IDs are passed per-request when fetching tools or via `getTools({ accountIds: [...] })`.

## Next Steps

* [OpenAI Integration](/agents/typescript/frameworks/openai-integration) for building agents with function calling
* [Vercel AI SDK](/agents/typescript/frameworks/vercel-ai-sdk) for streaming workflows
* [Tool Search](/agents/typescript/tool-search) for natural language tool discovery
* [Tool Filtering](/agents/typescript/tool-filtering) for advanced filtering patterns
