---
title: "Add SDK to Your App"
url: "https://docs.caracal.run/get-started/add-sdk-to-your-app/"
markdown_url: "https://docs.caracal.run/markdown/get-started/add-sdk-to-your-app.md"
description: "Use the generated runtime profile from your first protected call in TypeScript, Python, or Go."
page_type: "workflow"
concepts: []
requires: []
---

# Add SDK to Your App

Canonical URL: https://docs.caracal.run/get-started/add-sdk-to-your-app/
Markdown URL: https://docs.caracal.run/markdown/get-started/add-sdk-to-your-app.md
Description: Use the generated runtime profile from your first protected call in TypeScript, Python, or Go.
Page type: workflow
Concepts: none
Requires: none

---

This page shows the smallest SDK integration in TypeScript, Python, and Go. Each example opens an agent session, calls a Gateway-protected resource, and leaves authorization and action-result audit behind.

Complete [First Protected Call](/get-started/first-protected-call/) first so you have a generated runtime profile, a resource ID, and a protected path.

## Use the Runtime Profile

All SDKs can read the runtime profile generated by Console guided setup.

```sh
export CARACAL_CONFIG=/path/to/caracal.toml
export CARACAL_RESOURCE_ID=resource://example-api
export CARACAL_RESOURCE_PATH=/
```

On Windows PowerShell:

```powershell
$env:CARACAL_CONFIG = "C:\path\to\caracal.toml"
$env:CARACAL_RESOURCE_ID = "resource://example-api"
$env:CARACAL_RESOURCE_PATH = "/"
```

The profile supplies the zone, application, STS URL, Coordinator URL, app secret file, Gateway URL, and resource bindings. The resource variables choose which configured resource and path these examples call.

## Install the SDK

Install the package for your application language.

| Language | Install command | Runtime requirement |
| --- | --- | --- |
| TypeScript | `npm install @caracalai/sdk` or `pnpm add @caracalai/sdk` | Node.js 22+ |
| Python | `pip install caracalai-sdk` | Python 3.12+ |
| Go | `go get github.com/garudex-labs/caracal/packages/sdk/go` | Go 1.26+ |

## TypeScript

```typescript
import { Caracal } from "@caracalai/sdk";

const caracal = new Caracal();
const resourceId = process.env.CARACAL_RESOURCE_ID;
const resourcePath = process.env.CARACAL_RESOURCE_PATH;

if (!resourceId) throw new Error("CARACAL_RESOURCE_ID is required");
if (!resourcePath) throw new Error("CARACAL_RESOURCE_PATH is required");

await caracal.spawn(async () => {
  const ctx = caracal.current();
  console.log("Agent session:", ctx?.agentSessionId);

  const response = await caracal.fetch(resourceId, resourcePath, {
    method: "GET",
  });

  console.log(await response.text());
});
```

## Python

```python
import asyncio
import os

from caracalai import Caracal

caracal = Caracal()
resource_id = os.environ["CARACAL_RESOURCE_ID"]
resource_path = os.environ["CARACAL_RESOURCE_PATH"]

async def main():
    async with caracal.spawn() as ctx:
        print("Agent session:", ctx.agent_session_id)

        response = await caracal.fetch(
            resource_id,
            resource_path,
            method="GET",
        )
        print(response.text)

asyncio.run(main())
```

## Go

```go
package main

import (
    "context"
    "fmt"
    "io"
    "net/http"
    "os"

    caracal "github.com/garudex-labs/caracal/packages/sdk/go"
)

func main() {
    c, err := caracal.New()
    if err != nil {
        panic(err)
    }

    resourceID := os.Getenv("CARACAL_RESOURCE_ID")
    resourcePath := os.Getenv("CARACAL_RESOURCE_PATH")
    if resourceID == "" || resourcePath == "" {
        panic("CARACAL_RESOURCE_ID and CARACAL_RESOURCE_PATH are required")
    }

    err = c.Spawn(context.Background(), func(ctx context.Context) error {
        cc, _ := c.Current(ctx)
        fmt.Println("Agent session:", cc.AgentSessionID)

        resp, err := c.Fetch(ctx, http.MethodGet, resourceID, resourcePath)
        if err != nil {
            return err
        }
        defer resp.Body.Close()

        body, _ := io.ReadAll(resp.Body)
        fmt.Println(string(body))
        return nil
    })
    if err != nil {
        panic(err)
    }
}
```

## SDK Calls

| Call | Role |
| --- | --- |
| `new Caracal()` / `Caracal()` / `New()` | Loads the generated profile or environment configuration and prepares token exchange. |
| `spawn()` / `Spawn()` | Creates an agent session, binds context for the work, and terminates the session when the block exits. |
| `fetch()` / `Fetch()` | Sends one request to a resource through the Gateway with context and authority injected. |
| `gatewayRequest()` / `GatewayRequest()` | Builds the Gateway URL and `X-Caracal-Resource` header for explicit resource routing. |
| `transport()` / `Transport()` | Injects Caracal context, authorization, trace, and baggage headers on outbound calls. |

`spawn()` creates an agent session under the application from your runtime profile. You reuse that one application for every agent session your workload spawns; you do not register an application per agent. See [Should I create one application per agent?](/reference/faq/#faq-006).

If policy denies the exchange, STS returns HTTP 403 and the SDK surfaces an error. Open Console **audit** or **explain** with the request ID to see the policy and diagnostics that determined the result.

## Next Step

Use [First-Run Troubleshooting](/get-started/first-run-troubleshooting/) if the SDK cannot read the profile, exchange authority, call the Gateway, or find audit evidence. Otherwise continue to [Tutorials](/tutorials/).
