# API Reference Source: https://docs.castari.com/api-reference/introduction Castari REST API documentation # API Reference The Castari API lets you programmatically manage agents, deployments, and invocations. ## Base URL ``` https://api.castari.com ``` ## Authentication All API requests require authentication via the `Authorization` header with a Bearer token. ### API Key (Recommended) Include your API key as a Bearer token: ```bash theme={null} curl https://api.castari.com/api/v1/agents \ -H "Authorization: Bearer cast_xxxxxxxx_xxxxxxxxxx" ``` API keys look like: `cast_xxxxxxxx_xxxxxxxxxx` Generate one in the [Castari Dashboard](https://app.castari.com). ### OAuth Token You can also use a Clerk JWT token: ```bash theme={null} curl https://api.castari.com/api/v1/agents \ -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." ``` ## Rate Limits | Endpoint Type | Limit | | ----------------------------------------------- | ------------------- | | CRUD operations (GET, POST, PUT, PATCH, DELETE) | 100 requests/minute | | Invocations | 10 requests/minute | Rate limit headers are included in all responses: | Header | Description | | ----------------------- | -------------------------------- | | `X-RateLimit-Limit` | Maximum requests allowed | | `X-RateLimit-Remaining` | Requests remaining in window | | `X-RateLimit-Reset` | Unix timestamp when limit resets | When rate limited, you'll receive a `429 Too Many Requests` response: ```json theme={null} { "detail": "Rate limit exceeded. Try again in 30 seconds." } ``` ## Errors All errors return JSON with a `detail` field: ```json theme={null} { "detail": "Agent not found" } ``` ### Error Codes | Status | Meaning | | ------ | ------------------------------------------------ | | `400` | Bad Request — Invalid parameters | | `401` | Unauthorized — Missing or invalid authentication | | `403` | Forbidden — Insufficient permissions | | `404` | Not Found — Resource doesn't exist | | `422` | Validation Error — Invalid request body | | `429` | Rate Limited — Too many requests | | `500` | Server Error — Something went wrong | ### Validation Errors For `422` responses, errors include field-level details: ```json theme={null} { "detail": [ { "loc": ["body", "slug"], "msg": "field required", "type": "value_error.missing" } ] } ``` ## Pagination List endpoints support pagination: ```bash theme={null} GET /api/v1/agents?limit=10&offset=0 ``` | Parameter | Default | Description | | --------- | ------- | --------------------------- | | `limit` | 20 | Max items to return (1-100) | | `offset` | 0 | Number of items to skip | ## Endpoints Overview ### Agents | Method | Endpoint | Description | | -------- | ------------------------------- | ------------------------------- | | `GET` | `/api/v1/agents` | List all agents | | `POST` | `/api/v1/agents` | Create an agent | | `GET` | `/api/v1/agents/{slug}` | Get agent details | | `PATCH` | `/api/v1/agents/{slug}` | Update an agent | | `DELETE` | `/api/v1/agents/{slug}` | Delete an agent | | `POST` | `/api/v1/agents/{slug}/deploy` | Deploy an agent | | `DELETE` | `/api/v1/agents/{slug}/sandbox` | Stop an agent (destroy sandbox) | | `POST` | `/api/v1/agents/{slug}/invoke` | Invoke an agent | ### Secrets | Method | Endpoint | Description | | -------- | ------------------------------------- | --------------- | | `GET` | `/api/v1/agents/{slug}/secrets` | List secrets | | `POST` | `/api/v1/agents/{slug}/secrets` | Set a secret | | `DELETE` | `/api/v1/agents/{slug}/secrets/{key}` | Delete a secret | ### Sessions | Method | Endpoint | Description | | -------- | ------------------------------------- | ---------------- | | `GET` | `/api/v1/agents/{slug}/sessions` | List sessions | | `DELETE` | `/api/v1/agents/{slug}/sessions/{id}` | Delete a session | ### Invocations | Method | Endpoint | Description | | ------ | ----------------------------------- | ----------------------- | | `GET` | `/api/v1/agents/{slug}/invocations` | List invocation history | ### API Keys | Method | Endpoint | Description | | -------- | ----------------------- | -------------------- | | `GET` | `/api/v1/api-keys` | List all API keys | | `POST` | `/api/v1/api-keys` | Create a new API key | | `DELETE` | `/api/v1/api-keys/{id}` | Revoke an API key | ### Usage | Method | Endpoint | Description | | ------ | --------------------- | ------------------- | | `GET` | `/api/v1/usage` | Get usage summary | | `GET` | `/api/v1/usage/daily` | Get daily breakdown | ### Storage (Buckets) | Method | Endpoint | Description | | -------- | ------------------------------------ | ---------------------- | | `GET` | `/api/v1/buckets` | List all buckets | | `POST` | `/api/v1/buckets` | Create a bucket | | `GET` | `/api/v1/buckets/{slug}` | Get bucket details | | `PATCH` | `/api/v1/buckets/{slug}` | Update a bucket | | `DELETE` | `/api/v1/buckets/{slug}` | Delete a bucket | | `POST` | `/api/v1/buckets/{slug}/credentials` | Set bucket credentials | | `POST` | `/api/v1/buckets/{slug}/test` | Test bucket connection | ### Mounts | Method | Endpoint | Description | | -------- | ----------------------------------- | ------------------------ | | `GET` | `/api/v1/agents/{slug}/mounts` | List mounts for an agent | | `POST` | `/api/v1/agents/{slug}/mounts` | Add a mount | | `PATCH` | `/api/v1/agents/{slug}/mounts/{id}` | Update a mount | | `DELETE` | `/api/v1/agents/{slug}/mounts/{id}` | Remove a mount | ### Files (Managed Storage v2) | Method | Endpoint | Description | | -------- | ----------------------------- | -------------------- | | `GET` | `/api/v1/files` | List files | | `POST` | `/api/v1/files` | Upload a file | | `GET` | `/api/v1/files/{id}` | Get file metadata | | `PATCH` | `/api/v1/files/{id}` | Update file metadata | | `DELETE` | `/api/v1/files/{id}` | Delete a file | | `GET` | `/api/v1/files/{id}/download` | Download a file | | `GET` | `/api/v1/files/usage` | Get storage usage | ## SDKs For easier integration, use our official SDKs: * **TypeScript/JavaScript:** `npm install @castari/sdk` * **CLI:** `npm install -g @castari/cli` See the [SDK Reference](/sdk/overview) for details. ## Example: Full Workflow ```bash theme={null} # 1. Create an agent curl -X POST https://api.castari.com/api/v1/agents \ -H "Authorization: Bearer cast_xxx" \ -H "Content-Type: application/json" \ -d '{"name": "My Agent", "slug": "my-agent"}' # 2. Deploy the agent curl -X POST https://api.castari.com/api/v1/agents/my-agent/deploy \ -H "Authorization: Bearer cast_xxx" # 3. Invoke the agent curl -X POST https://api.castari.com/api/v1/agents/my-agent/invoke \ -H "Authorization: Bearer cast_xxx" \ -H "Content-Type: application/json" \ -d '{"prompt": "Hello, world!"}' ``` # cast agents Source: https://docs.castari.com/cli/agents List and manage agents # cast agents Commands for listing and managing your agents. ## cast agents list List all your agents. ### Usage ```bash theme={null} cast agents list ``` ### Output ``` NAME SLUG STATUS CREATED My Agent my-agent active 2024-01-15 Research Bot research-bot active 2024-01-14 Test Agent test-agent stopped 2024-01-10 ``` *** ## cast agents get Get details for a specific agent. ### Usage ```bash theme={null} cast agents get ``` ### Example ```bash theme={null} cast agents get my-agent ``` ### Output ``` Name: My Agent Slug: my-agent Status: active Created: 2024-01-15 10:30:00 Updated: 2024-01-15 14:22:00 Sandbox ID: sbx_xyz789 Git Repo: https://github.com/user/my-agent ``` *** ## cast agents create Create a new agent without deploying. ### Usage ```bash theme={null} cast agents create [options] ``` ### Arguments | Argument | Description | Required | | --------- | -------------------------- | -------- | | `name` | Display name for the agent | Yes | | `git-url` | Git repository URL | Yes | ### Options | Option | Description | | --------------- | ------------------------------------------------------ | | `--slug ` | Custom slug (auto-generated from name if not provided) | ### Example ```bash theme={null} cast agents create "My Agent" https://github.com/user/my-agent ``` With a custom slug: ```bash theme={null} cast agents create "My Agent" https://github.com/user/my-agent --slug my-custom-slug ``` Most users should use `cast init` + `cast deploy` instead of `cast agents create`. This command is for advanced use cases. *** ## cast agents delete Delete an agent. ### Usage ```bash theme={null} cast agents delete ``` ### Example ```bash theme={null} cast agents delete my-agent ``` ### Output ``` ? Are you sure you want to delete 'my-agent'? (y/N) y ✓ Agent 'my-agent' deleted ``` This permanently deletes the agent, its secrets, and all invocation history. This cannot be undone. ### Options | Option | Description | | ------------- | ------------------------ | | `-f, --force` | Skip confirmation prompt | ```bash theme={null} cast agents delete my-agent --force ``` *** ## See Also * [cast deploy](/cli/deploy) — Deploy an agent * [cast invoke](/cli/invoke) — Invoke an agent * [cast secrets](/cli/secrets) — Manage secrets # cast apikey Source: https://docs.castari.com/cli/apikey Manage API keys for authentication # cast apikey Manage API keys for programmatic access to the Castari API. Castari supports multiple named API keys per user. ## Subcommands | Command | Description | | ----------------------------- | -------------------- | | `cast apikey list` | List all API keys | | `cast apikey create` | Create a new API key | | `cast apikey revoke ` | Revoke an API key | *** ## cast apikey list List all API keys for the authenticated user. ### Usage ```bash theme={null} cast apikey list ``` ### Output Displays a table with key ID, name, prefix, creation date, and last used date. *** ## cast apikey create Create a new named API key. ### Usage ```bash theme={null} cast apikey create [--name ] ``` ### Options | Option | Description | Default | | --------------- | ------------------------------ | --------- | | `--name ` | A descriptive name for the key | `Default` | ### Example ```bash theme={null} cast apikey create --name "CI/CD Pipeline" ``` The full API key is only displayed once at creation. Store it securely — you will not be able to see it again. *** ## cast apikey revoke Revoke an existing API key. ### Usage ```bash theme={null} cast apikey revoke ``` ### Arguments | Argument | Description | Required | | -------- | ------------------------------- | -------- | | `key-id` | The ID of the API key to revoke | Yes | ### Example ```bash theme={null} cast apikey revoke ak_abc123 ``` ## See Also * [Auth API (SDK)](/sdk/auth) — Manage API keys programmatically * [CLI Overview](/cli/overview) — All CLI commands # cast buckets Source: https://docs.castari.com/cli/buckets Manage cloud storage buckets # cast buckets Manage cloud storage buckets for agent file access. Supports Amazon S3, Google Cloud Storage, and Cloudflare R2. ## Subcommands | Command | Description | | --------------------------------- | ------------------------ | | `cast buckets list` | List all storage buckets | | `cast buckets create ` | Create a new bucket | | `cast buckets get ` | Get bucket details | | `cast buckets delete ` | Delete a bucket | | `cast buckets test ` | Test bucket connection | | `cast buckets credentials ` | Set bucket credentials | *** ## cast buckets list List all configured storage buckets. ### Usage ```bash theme={null} cast buckets list ``` *** ## cast buckets create Create a new storage bucket configuration. ### Usage ```bash theme={null} cast buckets create [options] ``` ### Arguments | Argument | Description | Required | | -------- | --------------------------- | -------- | | `name` | Display name for the bucket | Yes | ### Options | Option | Description | Required | | ----------------------- | ---------------------------------------- | ------------------- | | `--slug ` | URL-safe identifier | No (auto-generated) | | `--provider ` | Storage provider: `s3`, `gcs`, or `r2` | Yes | | `--bucket-name ` | Actual bucket name in the cloud provider | Yes | | `--region ` | AWS region (for S3) | No | | `--endpoint ` | Custom endpoint URL (required for R2) | No | ### Example ```bash theme={null} cast buckets create "Production Data" \ --provider s3 \ --bucket-name my-data-bucket \ --region us-east-1 ``` *** ## cast buckets get Get details for a specific bucket. ### Usage ```bash theme={null} cast buckets get ``` *** ## cast buckets delete Delete a bucket configuration. ### Usage ```bash theme={null} cast buckets delete [-f, --force] ``` *** ## cast buckets test Test the connection to a bucket. ### Usage ```bash theme={null} cast buckets test ``` Verifies that the configured credentials can access the bucket. *** ## cast buckets credentials Set credentials for a bucket. ### Usage ```bash theme={null} cast buckets credentials [options] ``` ### Options | Option | Description | | ------------------------------- | ------------------------------------- | | `--access-key-id ` | AWS/R2 access key ID | | `--secret-access-key ` | AWS/R2 secret access key | | `--service-account-file ` | Path to GCS service account JSON file | ### Example (S3/R2) ```bash theme={null} cast buckets credentials my-bucket \ --access-key-id AKIAIOSFODNN7EXAMPLE \ --secret-access-key wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY ``` ### Example (GCS) ```bash theme={null} cast buckets credentials my-gcs-bucket \ --service-account-file ./service-account.json ``` ## See Also * [cast mounts](/cli/mounts) — Mount buckets to agents * [Storage API (SDK)](/sdk/storage) — Manage buckets programmatically # cast deploy Source: https://docs.castari.com/cli/deploy Deploy an agent to Castari # cast deploy Deploy an agent to Castari. ## Usage ```bash theme={null} cast deploy [slug] ``` ## Arguments | Argument | Description | Required | | -------- | ----------- | ----------------------------------------------------- | | `slug` | Agent slug | No (read from `castari.json` if in project directory) | ## Examples ### Deploy from a Castari project directory If you're inside a directory with a `castari.json` file, just run: ```bash theme={null} cast deploy ``` The CLI reads the `slug` field from `castari.json`. If no `slug` field is present, it derives the slug from the `name` field. ### Deploy a specific agent ```bash theme={null} cast deploy my-agent ``` Deploys the agent with slug `my-agent`, pulling code from its configured git repository. ## What Happens During Deploy Code is pulled from the agent's configured git repository. An isolated E2B sandbox is created for your agent. `npm install` runs inside the sandbox. Any secrets you've set become environment variables. Agent status becomes `active`. Ready to invoke. ## Agent Configuration Your agent needs a `castari.json` file: ```json theme={null} { "name": "my-agent", "slug": "my-agent", "version": "0.1.0", "entrypoint": "src/index.ts", "runtime": "node" } ``` ## Redeploying Running `cast deploy` on an already-deployed agent will redeploy it: 1. Previous sandbox is destroyed 2. New sandbox is created 3. Latest code is deployed Redeploying does not preserve sandbox state. All files and data in the sandbox are lost. ## Errors | Error | Cause | Fix | | ------------------------- | -------------------------- | ----------------------------------------------------- | | `Agent not found` | Invalid slug | Check `cast agents list` for correct slug | | `castari.json not found` | Not in a project directory | Specify the slug explicitly or `cd` to your project | | `npm install failed` | Dependency error | Check `package.json`, run `npm install` locally first | | `Authentication required` | Not logged in | Run `cast login` | ## See Also * [cast init](/cli/init) — Create a new agent from a template * [cast invoke](/cli/invoke) — Invoke a deployed agent * [Your First Agent](/first-agent) — Understand agent structure # cast files Source: https://docs.castari.com/cli/files Manage files in Castari storage # cast files Manage files in Castari's managed storage. Upload, list, and manage files that can be attached to agents. ## Command Overview | Command | Description | | --------------------- | --------------------- | | `cast files list` | List files in storage | | `cast files upload` | Upload a file | | `cast files get` | Get file details | | `cast files delete` | Delete a file | | `cast files download` | Download a file | | `cast files usage` | Show storage usage | *** ## cast files list List files in your managed storage. ### Usage ```bash theme={null} cast files list [options] ``` ### Options | Option | Description | | ------------------ | ------------------------------------------- | | `--limit ` | Maximum files to return (default: 50) | | `--offset ` | Number of files to skip (default: 0) | | `--scope ` | Filter by scope: `user`, `agent`, `session` | | `--tags ` | Filter by tags (comma-separated) | | `--search ` | Search in filename and description | ### Example ```bash theme={null} cast files list ``` ### Output ``` File ID Filename Size Scope Created file_abc123 training-data.csv 2.4 MB user Jan 15, 2024 file_def456 config.json 1.2 KB user Jan 14, 2024 file_ghi789 reference.txt 45.6 KB user Jan 13, 2024 ℹ Showing 3 of 3 files ``` ### Filter by Tags ```bash theme={null} cast files list --tags dataset,csv ``` ### Search Files ```bash theme={null} cast files list --search training ``` *** ## cast files upload Upload a file to managed storage. ### Usage ```bash theme={null} cast files upload [options] ``` ### Arguments | Argument | Description | | -------- | ------------------------- | | `path` | Local file path to upload | ### Options | Option | Description | | ---------------------- | -------------------- | | `--description ` | File description | | `--tags ` | Comma-separated tags | ### Example ```bash theme={null} cast files upload data.csv --description "Training data" --tags dataset,ml ``` ### Output ``` ✓ Uploaded data.csv File ID file_abc123 Size 2.4 MB → Attach to agent: cast agents files add file_abc123 ``` Files larger than 10MB automatically use presigned uploads for better performance. *** ## cast files get Get detailed information about a file. ### Usage ```bash theme={null} cast files get ``` ### Example ```bash theme={null} cast files get file_abc123 ``` ### Output ``` File ID file_abc123 Filename data.csv Size 2.4 MB Content Type text/csv Scope user Status confirmed Description Training data Tags dataset, ml SHA256 a1b2c3d4e5f6... Created Jan 15, 2024 10:30 AM Updated Jan 15, 2024 10:30 AM ``` *** ## cast files delete Delete a file from storage. ### Usage ```bash theme={null} cast files delete [options] ``` ### Options | Option | Description | | ------------- | ------------------------ | | `-f, --force` | Skip confirmation prompt | ### Example ```bash theme={null} cast files delete file_abc123 ``` ### Output ``` Are you sure you want to delete file 'file_abc123'? [y/N] y ✓ File 'file_abc123' deleted ``` Deleting a file will also detach it from any agents it was attached to. *** ## cast files download Download a file from storage. ### Usage ```bash theme={null} cast files download [options] ``` ### Options | Option | Description | | ----------------- | --------------------------------------------- | | `--output ` | Output file path (default: original filename) | ### Example ```bash theme={null} cast files download file_abc123 --output ./local-data.csv ``` ### Output ``` ✓ Downloaded to ./local-data.csv ℹ Size: 2.4 MB ``` *** ## cast files usage Show your storage usage and quota. ### Usage ```bash theme={null} cast files usage ``` ### Example ```bash theme={null} cast files usage ``` ### Output ``` Total Files 12 Total Size 45.2 MB Quota Used 45.2% Quota Limit 100 MB ████████████████████░░░░░░░░░░░░░░░░░░░░ 45.2% ``` *** ## Agent Files Commands Manage files attached to specific agents. ### cast agents files list List files attached to an agent. ```bash theme={null} cast agents files list ``` #### Example ```bash theme={null} cast agents files list my-agent ``` #### Output ``` File ID Filename Mount Path Size Mode file_abc123 data.csv /files/agent/data.csv 2.4 MB ro file_def456 config.json /files/agent/config.json 1.2 KB ro ℹ 2 files attached (2.4 MB total) ``` *** ### cast agents files add Attach a file to an agent. ```bash theme={null} cast agents files add [options] ``` #### Options | Option | Description | | --------------------- | ------------------------------------------------------ | | `--mount-path ` | Custom mount path (default: `/files/agent/`) | | `--writable` | Make file writable (default: read-only) | #### Example ```bash theme={null} cast agents files add my-agent file_abc123 ``` #### Output ``` ✓ File attached to agent 'my-agent' File ID file_abc123 Filename data.csv Mount Path /files/agent/data.csv Mode read-only → File will be available at /files/agent/data.csv in the sandbox ``` *** ### cast agents files remove Detach a file from an agent. ```bash theme={null} cast agents files remove [options] ``` #### Options | Option | Description | | ------------- | ------------------------ | | `-f, --force` | Skip confirmation prompt | #### Example ```bash theme={null} cast agents files remove my-agent file_abc123 ``` #### Output ``` Detach file 'file_abc123' from agent 'my-agent'? [y/N] y ✓ File 'file_abc123' detached from agent 'my-agent' ``` *** ## Workflow Example Complete workflow for using files with an agent: ```bash theme={null} # 1. Upload a file cast files upload training-data.csv --description "ML training data" # → file_abc123 # 2. Attach to agent cast agents files add my-ml-agent file_abc123 # 3. Verify attachment cast agents files list my-ml-agent # 4. Deploy and run agent cast deploy my-ml-agent cast invoke my-ml-agent "Process the training data" # 5. Clean up when done cast agents files remove my-ml-agent file_abc123 ``` ## See Also * [Managed Files Concept](/concepts/files) — How managed files work * [Storage Buckets](/guides/storage) — BYO storage for large datasets # cast init Source: https://docs.castari.com/cli/init Create a new agent from a template # cast init Create a new agent from a template. ## Usage ```bash theme={null} cast init [options] ``` ## Arguments | Argument | Description | Required | | -------- | -------------------------------- | -------- | | `name` | Name for the new agent directory | Yes | ## Options | Option | Description | Default | | ----------------------- | ------------------ | ------------------ | | `-t, --template ` | Template to use | Interactive prompt | | `--no-install` | Skip `npm install` | `false` | ## Templates | Template | Description | | ---------------- | -------------------------------------------------------- | | `default` | Coding agent with file and bash tools (like Claude Code) | | `research-agent` | Deep research with web search and document synthesis | | `support-agent` | Customer support with ticket handling and escalation | | `mcp-tools` | Agent with example MCP server integration | ## Examples ### Interactive mode ```bash theme={null} cast init my-agent ``` Prompts you to select a template: ``` ? Select a template: ❯ default — Coding agent with file and bash tools (like Claude Code) research-agent — Deep research with web search and document synthesis support-agent — Customer support with ticket handling and escalation mcp-tools — Agent with example MCP server integration ✓ Created my-agent/ from default template ✓ Installed dependencies ``` ### Specify template ```bash theme={null} cast init my-agent --template research-agent ``` ### Skip npm install ```bash theme={null} cast init my-agent --no-install ``` ## Created Files ``` my-agent/ ├── castari.json # Agent configuration ├── package.json # Dependencies ├── tsconfig.json # TypeScript config ├── src/ │ └── index.ts # Agent entry point ├── CLAUDE.md # Agent instructions └── README.md # Documentation ``` ## Next Steps After creating an agent: ```bash theme={null} cd my-agent cast deploy ``` ## See Also * [Your First Agent](/first-agent) — Understand agent structure * [Templates Guide](/guides/templates) — Detailed template documentation * [cast deploy](/cli/deploy) — Deploy your agent # cast invoke Source: https://docs.castari.com/cli/invoke Invoke a deployed agent # cast invoke Send a prompt to a deployed agent and get a response. ## Usage ```bash theme={null} cast invoke [prompt] [options] ``` ## Arguments | Argument | Description | Required | | -------- | ------------------ | ------------------------- | | `slug` | Agent slug | Yes | | `prompt` | The prompt to send | No (can use `-i` instead) | ## Options | Option | Description | | -------------------- | ------------------------------------------------------- | | `-i, --input ` | Read prompt from a file | | `-s, --session ` | Session ID for conversation continuity (reuses sandbox) | ## Examples ### Basic invocation ```bash theme={null} cast invoke my-agent "What files are in the current directory?" ``` Output: ``` The current directory contains: - src/index.ts - package.json - castari.json - CLAUDE.md - README.md ``` ### Read prompt from a file ```bash theme={null} cast invoke my-agent -i prompt.txt ``` Useful for longer prompts or multi-line input. ### Multi-turn conversations Use the `-s, --session` option to maintain conversation history: ```bash theme={null} # Start a session cast invoke my-agent "Create a file called hello.txt" -s my-session # Continue the same session (sandbox state preserved) cast invoke my-agent "What's in the file you just created?" -s my-session ``` With session IDs, the agent's sandbox persists between invocations, allowing multi-turn conversations and stateful interactions. ## What Happens During Invoke 1. **Request received** — Your prompt is sent to the Castari API 2. **Sandbox activated** — A sandbox is spun up (or reused if session specified) 3. **Agent runs** — Your agent code executes with the prompt as input 4. **Response collected** — Output is captured and returned to you 5. **Cleanup** — Without a session, sandbox is destroyed. With a session, it persists. ## Errors | Error | Cause | Fix | | ------------------- | ------------------- | ----------------------------------------- | | `Agent not found` | Invalid slug | Check `cast agents list` for correct slug | | `Agent not active` | Agent not deployed | Run `cast deploy` first | | `Timeout exceeded` | Agent took too long | Optimize your agent | | `Invocation failed` | Agent error | Check agent logs in dashboard | ## See Also * [cast deploy](/cli/deploy) — Deploy an agent * [SDK invoke](/sdk/agents#invokeslug-options) — Invoke programmatically # cast login Source: https://docs.castari.com/cli/login Authenticate with Castari # cast login Authenticate with Castari via browser-based OAuth. ## Usage ```bash theme={null} cast login ``` ## What Happens 1. Opens your default browser to Castari login page 2. You sign in (or create an account) 3. Browser redirects back, CLI captures the token 4. Credentials saved to `~/.castari/credentials.json` ## Output ``` Opening browser to authenticate... ✓ Logged in as you@example.com ``` ## Options | Option | Description | | -------------- | ------------------------------------------ | | `--no-browser` | Print login URL instead of opening browser | ### Headless Authentication For CI/CD or headless environments: ```bash theme={null} cast login --no-browser ``` This prints the URL for manual authentication. For automated environments, use an API key instead of OAuth. See [Environment Variables](/cli/overview#environment-variables). *** # cast logout Clear stored credentials. ## Usage ```bash theme={null} cast logout ``` ## Output ``` ✓ Logged out ``` This deletes `~/.castari/credentials.json`. *** # cast whoami Show the currently authenticated user. ## Usage ```bash theme={null} cast whoami ``` ## Output ``` Logged in as: you@example.com User ID: usr_abc123 ``` If not logged in: ``` Not logged in. Run 'cast login' to authenticate. ``` ## See Also * [Installation](/installation) — Install the CLI * [Quick Start](/quickstart) — Deploy your first agent # cast mounts Source: https://docs.castari.com/cli/mounts Mount storage buckets to agents # cast mounts Mount cloud storage buckets to agent sandboxes, giving agents read or write access to external files. ## Subcommands | Command | Description | | -------------------------------------------- | ------------------------ | | `cast mounts list ` | List mounts for an agent | | `cast mounts add ` | Add a mount to an agent | | `cast mounts update ` | Update a mount | | `cast mounts remove ` | Remove a mount | *** ## cast mounts list List all mounts for an agent. ### Usage ```bash theme={null} cast mounts list ``` *** ## cast mounts add Add a storage bucket mount to an agent. ### Usage ```bash theme={null} cast mounts add [options] ``` ### Options | Option | Description | Required | | ------------------- | ----------------------------- | -------- | | `--bucket ` | Bucket slug to mount | Yes | | `--path ` | Mount path inside the sandbox | Yes | | `--prefix ` | Source prefix in the bucket | No | | `--read-only` | Mount as read-only | No | ### Example ```bash theme={null} cast mounts add my-agent \ --bucket production-data \ --path /data \ --read-only ``` *** ## cast mounts update Update an existing mount. ### Usage ```bash theme={null} cast mounts update [options] ``` ### Options | Option | Description | | ------------------- | ----------------- | | `--path ` | New mount path | | `--prefix ` | New source prefix | | `--enable` | Enable the mount | | `--disable` | Disable the mount | *** ## cast mounts remove Remove a mount from an agent. ### Usage ```bash theme={null} cast mounts remove [-f, --force] ``` After modifying mounts, redeploy the agent for changes to take effect. ## See Also * [cast buckets](/cli/buckets) — Manage storage buckets * [Mounts API (SDK)](/sdk/mounts) — Manage mounts programmatically # CLI Overview Source: https://docs.castari.com/cli/overview The cast command-line interface # CLI Overview The `cast` CLI is the fastest way to deploy and manage agents on Castari. ## Installation ```bash theme={null} npm install -g @castari/cli ``` ## Commands | Command | Description | | ------------------------------------------------------------ | ---------------------------------- | | [`cast login`](/cli/login) | Authenticate with Castari | | [`cast logout`](/cli/login#logout) | Clear stored credentials | | [`cast whoami`](/cli/whoami) | Show current user | | [`cast init`](/cli/init) | Create a new agent from a template | | [`cast deploy`](/cli/deploy) | Deploy an agent | | [`cast stop`](/cli/stop) | Stop a running agent | | [`cast invoke`](/cli/invoke) | Invoke a deployed agent | | [`cast agents list`](/cli/agents) | List all agents | | [`cast agents get`](/cli/agents#cast-agents-get) | Get agent details | | [`cast agents update`](/cli/agents) | Update agent configuration | | [`cast agents delete`](/cli/agents#cast-agents-delete) | Delete an agent | | [`cast secrets list`](/cli/secrets) | List secrets for an agent | | [`cast secrets set`](/cli/secrets#cast-secrets-set) | Set a secret | | [`cast secrets delete`](/cli/secrets#cast-secrets-delete) | Delete a secret | | [`cast apikey list`](/cli/apikey) | List API keys | | [`cast apikey create`](/cli/apikey#cast-apikey-create) | Create a new API key | | [`cast apikey revoke`](/cli/apikey#cast-apikey-revoke) | Revoke an API key | | [`cast usage`](/cli/usage) | Show usage statistics | | [`cast buckets`](/cli/buckets) | Manage storage buckets | | [`cast mounts`](/cli/mounts) | Mount buckets to agents | | [`cast files`](/cli/files) | Manage files in storage | | [`cast sessions list`](/cli/sessions) | List agent sessions | | [`cast sessions delete`](/cli/sessions#cast-sessions-delete) | Delete a session | | [`cast invocations list`](/cli/agents) | List invocation history | ## Global Options All commands support these options: | Option | Description | | ----------- | ----------------------- | | `--help` | Show help for a command | | `--version` | Show CLI version | ## Configuration The CLI stores configuration in `~/.castari/`: ``` ~/.castari/ ├── config.json # API URL, preferences └── credentials.json # Auth tokens (do not share!) ``` ## Environment Variables | Variable | Description | | ----------------- | ---------------------------- | | `CASTARI_API_URL` | Override API base URL | | `CASTARI_API_KEY` | Use API key instead of OAuth | ## Examples ```bash theme={null} # Full workflow cast login cast init my-agent cd my-agent cast deploy cast invoke my-agent "Hello!" # Check agent status cast agents get my-agent # Add a secret cast secrets set my-agent OPENAI_API_KEY sk-xxx ``` # cast secrets Source: https://docs.castari.com/cli/secrets Manage agent secrets and environment variables # cast secrets Manage secrets for your agents. Secrets are injected as environment variables when the agent runs. ## cast secrets list List all secrets for an agent. ### Usage ```bash theme={null} cast secrets list ``` ### Example ```bash theme={null} cast secrets list my-agent ``` ### Output ``` KEY CREATED OPENAI_API_KEY 2024-01-15 10:30:00 DATABASE_URL 2024-01-15 10:30:00 ``` Secret values are never displayed. Only the keys and creation dates are shown. *** ## cast secrets set Set a secret for an agent. ### Usage ```bash theme={null} cast secrets set ``` ### Arguments | Argument | Description | | -------- | ----------------------------------- | | `slug` | Agent slug | | `key` | Secret name (uppercase recommended) | | `value` | Secret value | ### Examples ```bash theme={null} # Set an API key cast secrets set my-agent OPENAI_API_KEY sk-abc123... # Set a database URL cast secrets set my-agent DATABASE_URL postgres://user:pass@host/db ``` ### Output ``` ✓ Secret 'OPENAI_API_KEY' set for agent 'my-agent' ``` Setting a secret with an existing key will overwrite the previous value. ### Interactive Mode To avoid exposing secrets in shell history: ```bash theme={null} cast secrets set my-agent OPENAI_API_KEY ``` When no value is provided, you'll be prompted to enter it securely: ``` Enter value for OPENAI_API_KEY: ******** ✓ Secret 'OPENAI_API_KEY' set for agent 'my-agent' ``` *** ## cast secrets delete Delete a secret from an agent. ### Usage ```bash theme={null} cast secrets delete ``` ### Example ```bash theme={null} cast secrets delete my-agent OPENAI_API_KEY ``` ### Output ``` ✓ Secret 'OPENAI_API_KEY' deleted from agent 'my-agent' ``` *** ## Using Secrets in Agents Secrets are available as environment variables in your agent code: ```typescript theme={null} // Access secrets in your agent const openaiKey = process.env.OPENAI_API_KEY; const databaseUrl = process.env.DATABASE_URL; ``` ## Built-in Secrets Castari automatically provides these environment variables: | Variable | Description | | ------------------- | ----------------------------------- | | `ANTHROPIC_API_KEY` | Your Anthropic API key (for Claude) | You don't need to set `ANTHROPIC_API_KEY` manually. Castari injects it automatically so your agents can use Claude. ## Best Practices 1. **Use uppercase names** — `DATABASE_URL` not `database_url` 2. **Don't commit secrets** — Never put secrets in your agent code or git 3. **Use descriptive names** — `STRIPE_SECRET_KEY` not `KEY1` 4. **Rotate regularly** — Update secrets periodically for security ## See Also * [Secrets Concept](/concepts/secrets) — How secrets work * [cast deploy](/cli/deploy) — Deploy with secrets # cast sessions Source: https://docs.castari.com/cli/sessions Manage agent sessions # cast sessions Manage sessions for deployed agents. Sessions allow multi-turn conversations that reuse the same sandbox. ## Subcommands | Command | Description | | ------------------------------------------ | -------------------------- | | `cast sessions list ` | List sessions for an agent | | `cast sessions delete ` | Delete a session | *** ## cast sessions list List all sessions for a deployed agent. ### Usage ```bash theme={null} cast sessions list ``` ### Arguments | Argument | Description | Required | | -------- | ----------------------- | -------- | | `slug` | The agent's unique slug | Yes | ### Output Displays a table with session ID, sandbox ID, creation date, and last invocation time. *** ## cast sessions delete Delete a specific session. ### Usage ```bash theme={null} cast sessions delete ``` ### Arguments | Argument | Description | Required | | ------------ | ------------------------ | -------- | | `slug` | The agent's unique slug | Yes | | `session-id` | The session ID to delete | Yes | ## See Also * [cast invoke](/cli/invoke) — Invoke an agent (use `--session` for multi-turn) * [Concepts: Invocations](/concepts/invocations) — How sessions work # cast stop Source: https://docs.castari.com/cli/stop Stop a running agent # cast stop Stop a running agent and destroy its sandbox. ## Usage ```bash theme={null} cast stop ``` ## Arguments | Argument | Description | Required | | -------- | ----------------------- | -------- | | `slug` | The agent's unique slug | Yes | ## Example ```bash theme={null} cast stop my-agent ``` Stopping an agent destroys its sandbox. All files and state inside the sandbox will be lost. The agent can be redeployed with `cast deploy`. ## What Happens 1. The agent's sandbox is destroyed via `DELETE /agents/{slug}/sandbox` 2. The agent status changes to `stopped` 3. The agent can no longer receive invocations until redeployed ## See Also * [cast deploy](/cli/deploy) — Deploy or redeploy an agent * [Agents API](/sdk/agents) — `agents.stop()` SDK method # cast usage Source: https://docs.castari.com/cli/usage View usage statistics # cast usage Show usage statistics for your Castari account. ## Usage ```bash theme={null} cast usage [--days ] [--daily] ``` ## Options | Option | Description | Default | | ------------------- | --------------------------------------- | ------- | | `-d, --days ` | Number of days to show | `30` | | `--daily` | Show daily breakdown instead of summary | Off | ## Examples ### Summary view (default) ```bash theme={null} cast usage ``` Displays total invocations, input/output tokens, and total cost for the period. ### Daily breakdown ```bash theme={null} cast usage --daily --days 7 ``` Shows a table with per-day invocations, tokens, and cost. ## See Also * [Usage API (SDK)](/sdk/usage) — Query usage programmatically * [CLI Overview](/cli/overview) — All CLI commands # cast whoami Source: https://docs.castari.com/cli/whoami Show current authenticated user # cast whoami Display information about the currently authenticated user. ## Usage ```bash theme={null} cast whoami ``` ## Output Shows the user's email address and API key prefix (if an API key is set). ## Example ```bash theme={null} $ cast whoami Email: user@example.com API Key: cast_abc12345... ``` ## See Also * [cast login](/cli/login) — Authenticate with Castari * [cast apikey](/cli/apikey) — Manage API keys # Agents Source: https://docs.castari.com/concepts/agents What agents are and how they work # Agents An agent is your Claude-powered application deployed on Castari. ## What is an Agent? An agent is a program that: 1. Receives a **prompt** as input 2. Uses **Claude** to reason and decide on actions 3. Executes **tools** to interact with the world 4. Returns a **response** Agents can do things like: * Read and write files * Execute shell commands * Search the web * Query databases * Call external APIs ## Agent Structure Every Castari agent has this structure: ``` my-agent/ ├── castari.json # Agent configuration ├── package.json # Dependencies ├── tsconfig.json # TypeScript config ├── src/ │ └── index.ts # Entry point ├── CLAUDE.md # Agent instructions └── README.md # Documentation ``` ### castari.json The agent configuration file: ```json theme={null} { "name": "my-agent", "version": "0.1.0", "entrypoint": "src/index.ts", "runtime": "node" } ``` | Field | Required | Description | | ------------ | -------- | ----------------- | | `name` | Yes | Display name | | `version` | Yes | Semantic version | | `entrypoint` | Yes | Path to main file | | `runtime` | Yes | Runtime (`node`) | ### CLAUDE.md Instructions for Claude that shape the agent's behavior: ```markdown theme={null} # Research Agent You are a research assistant that finds and synthesizes information. ## Guidelines - Always cite sources - Present multiple perspectives - Summarize findings at the end ``` ## Agent Lifecycle ``` draft → deploying → active → stopped ↓ error ``` | Status | Description | | ----------- | ------------------------------------ | | `draft` | Created but not yet deployed | | `deploying` | Deployment in progress | | `active` | Running and accepting invocations | | `stopped` | Manually stopped (can be redeployed) | | `error` | Deployment or runtime failure | ## Slugs and Naming Every agent has a **slug** — a URL-safe identifier: * Slugs are lowercase alphanumeric with hyphens * Example: `my-agent`, `research-bot-v2` * Slugs must be unique per user * Used in CLI commands: `cast invoke my-agent "Hello"` ## Entry Point Contract Your agent's entry point must: 1. **Read prompt from stdin** 2. **Process with Claude and tools** 3. **Write response to stdout** ```typescript theme={null} // Read let prompt = ""; process.stdin.on("data", (chunk) => (prompt += chunk)); process.stdin.on("end", async () => { // Process const response = await runAgent(prompt); // Write console.log(response); }); ``` ## Tools Agents use tools to take actions. Tools are defined as schemas: ```typescript theme={null} const tools: Anthropic.Tool[] = [ { name: "read_file", description: "Read the contents of a file", input_schema: { type: "object", properties: { path: { type: "string" } }, required: ["path"] } } ]; ``` When Claude decides to use a tool, your code executes it: ```typescript theme={null} async function handleTool(name: string, input: any): Promise { switch (name) { case "read_file": return fs.readFileSync(input.path, "utf-8"); // ... other tools } } ``` ## See Also Build and customize agents Start with pre-built agents Build from scratch Execution environment # Managed Files Source: https://docs.castari.com/concepts/files Simple file storage for agent data # Managed Files Castari provides zero-configuration file storage for your agents. Upload files, attach them to agents, and they automatically appear in the sandbox. ## Why Managed Files? Your agents often need access to: * Data files (CSV, JSON, etc.) * Configuration files * Documents for processing * Reference materials Managed files let you provide these **simply** without: * Setting up cloud storage buckets * Managing credentials * Configuring mount paths manually ## How It Works ```mermaid theme={null} graph LR A[Upload File] --> B[Attach to Agent] B --> C[Auto-mount in Sandbox] C --> D[Agent reads /files/agent/] ``` 1. **Upload** — Files go to Castari's managed storage 2. **Attach** — Link files to specific agents 3. **Mount** — Files automatically appear at `/files/agent/` in the sandbox ## File Scopes Files can be scoped for different uses: | Scope | Description | Mount Path | | --------- | ---------------------------- | ------------------- | | `user` | Your personal files | Available to attach | | `agent` | Attached to a specific agent | `/files/agent/` | | `session` | Per-invocation outputs | `/files/session/` | ## Uploading Files ### Via CLI ```bash theme={null} cast files upload data.csv --description "Training data" ``` ### Via Dashboard 1. Navigate to **Files** in the sidebar 2. Click **Upload File** 3. Select file and add optional description/tags ### Via SDK ```typescript theme={null} const result = await client.files.upload(fileBlob, 'data.csv', { description: 'Training data', tags: ['dataset', 'csv'], }); console.log(result.file_id); // file_abc123 ``` ## Attaching Files to Agents Once uploaded, attach files to agents: ### Via CLI ```bash theme={null} cast agents files add my-agent file_abc123 ``` ### Via Dashboard 1. Go to **Agents** → your agent 2. Find the **Attached Files** section 3. Click **Attach File** and select from your files ### Via SDK ```typescript theme={null} await client.files.attachToAgent('my-agent', { fileId: 'file_abc123', readOnly: true, }); ``` ## Using Files in Agents Attached files are available at `/files/agent/`: ```typescript theme={null} import { readFileSync } from 'fs'; // Read attached file const data = readFileSync('/files/agent/data.csv', 'utf-8'); // Parse and process const rows = data.split('\n').map(line => line.split(',')); ``` Files are read-only by default. Use `--writable` flag or set `readOnly: false` to allow writes. ## Storage Limits | Plan | Storage Limit | | ---------- | ------------- | | Free | 100 MB | | Pro | 10 GB | | Enterprise | Custom | Check your usage: ```bash theme={null} cast files usage ``` ``` Total Files 12 Total Size 45.2 MB Quota Used 45.2% Quota Limit 100 MB ████████████████████░░░░░░░░░░░░░░░░░░░░ 45.2% ``` ## Managed vs. BYO Storage Castari supports both managed files and bring-your-own storage buckets: | Feature | Managed Files | BYO Buckets | | -------- | ---------------- | --------------------- | | Setup | Zero config | Configure credentials | | Storage | Castari hosted | Your S3/GCS/R2 | | Cost | Included in plan | Your cloud costs | | Use case | Simple files | Large datasets | Use managed files for simplicity. Use [Storage Buckets](/guides/storage) for large datasets or when you need files in your own cloud. ## File Metadata Each file tracks: * **Filename** — Original name * **Size** — File size in bytes * **Content Type** — MIME type * **SHA256 Hash** — Integrity verification * **Description** — Optional description * **Tags** — Optional tags for organization ## Best Practices ### Organization * **Use descriptions** — Document what each file is for * **Tag consistently** — Use tags like `dataset`, `config`, `reference` * **Clean up** — Delete files you no longer need ### Security * **Don't upload secrets** — Use [Secrets](/concepts/secrets) for credentials * **Verify hashes** — Check SHA256 for critical files * **Review attachments** — Only attach files agents actually need ### Performance * **Keep files small** — For large datasets, use BYO storage * **Use appropriate formats** — CSV/JSON for structured data * **Consider caching** — Files are cached in the sandbox ## See Also CLI reference BYO storage setup # How Castari Works Source: https://docs.castari.com/concepts/how-it-works Architecture and key concepts # How Castari Works Understand how Castari deploys and runs your agents. ## Architecture Overview ``` ┌─────────────┐ ┌──────────────────┐ ┌─────────────┐ │ You │ │ Castari API │ │ E2B │ │ (CLI/SDK) │ ───▶ │ (Control Plane) │ ───▶ │ Sandboxes │ └─────────────┘ └──────────────────┘ └─────────────┘ │ ┌─────────┼─────────┐ ▼ ▼ ▼ PostgreSQL Redis Clerk Auth ``` **Control Plane** — Manages agents, secrets, invocations, and usage tracking. **E2B Sandboxes** — Isolated execution environments where your agents run. ## Deployment Flow When you run `cast deploy`: Your agent code is uploaded to Castari (or cloned from git). An isolated E2B sandbox is created for your agent. `npm install` runs inside the sandbox. Any secrets you've set become environment variables. Agent status becomes `active`. Ready to invoke. ## Invocation Flow When you run `cast invoke`: Your prompt is sent to the Castari API. A fresh sandbox is spun up for this request. Your agent code executes with the prompt as input. Output is captured and returned to you. Sandbox is destroyed. No state persists. ## Per-Request Scaling Every invocation gets a **fresh sandbox**. This means: * **No state leaks** — Each request is isolated * **True security** — No cross-request data exposure * **Automatic scaling** — Parallel invocations run in parallel sandboxes * **No cold starts** — Sandboxes are pre-warmed ## Agent Entry Point Contract Your agent communicates via stdin/stdout: ``` Input: prompt → stdin Output: response → stdout ``` Example: ```typescript theme={null} // Read prompt from stdin let prompt = ""; for await (const chunk of process.stdin) { prompt += chunk; } // Process and respond const response = await runAgent(prompt); // Write to stdout console.log(response); ``` ## Security Model | Layer | Protection | | ------- | -------------------------------------- | | Sandbox | Isolated E2B container | | Network | Egress allowed, no ingress | | Secrets | Encrypted at rest, injected at runtime | | Code | Your code, your sandbox, not shared | ## Resource Limits | Resource | Limit | | -------- | ----------- | | Memory | 2 GB | | CPU | 2 cores | | Timeout | 120 seconds | | Disk | 10 GB | Contact us if you need higher limits for production workloads. ## See Also Agent structure and lifecycle E2B sandbox details Environment variable management Request/response model # Invocations Source: https://docs.castari.com/concepts/invocations How agent requests and responses work # Invocations An invocation is a single request-response cycle with an agent. ## What is an Invocation? When you run: ```bash theme={null} cast invoke my-agent "What files are here?" ``` You create an **invocation** — a record of: * The prompt you sent * The response you received * Tokens used and cost * Execution time * Status (completed, failed) ## Invocation Flow ``` ┌──────────┐ prompt ┌──────────────┐ stdin ┌─────────┐ │ You │ ──────────▶ │ Castari API │ ─────────▶ │ Agent │ └──────────┘ └──────────────┘ └─────────┘ ▲ │ │ │ response │ stdout │ └───────────────────────────┴──────────────────────────┘ ``` 1. **Request** — You send a prompt via CLI, SDK, or API 2. **Routing** — Castari routes to your agent's sandbox 3. **Execution** — Agent processes prompt, uses tools, generates response 4. **Response** — Output captured and returned to you 5. **Tracking** — Tokens, cost, and duration recorded ## Input and Output ### Input Your prompt is passed to the agent via **stdin**: ```typescript theme={null} // Agent reads from stdin let prompt = ""; process.stdin.on("data", (chunk) => (prompt += chunk)); process.stdin.on("end", () => { // Process prompt }); ``` ### Output Agent response is written to **stdout**: ```typescript theme={null} // Agent writes to stdout console.log(response); ``` Only stdout is captured as the response. stderr is logged but not returned. ## Invocation Result Every invocation returns: ```typescript theme={null} { invocation_id: "inv_abc123", session_id: "sess_xyz789", response_content: "The current directory contains...", input_tokens: 124, output_tokens: 1110, total_cost_usd: 0.02, duration_ms: 2341, status: "completed" } ``` | Field | Description | | ------------------ | ----------------------- | | `invocation_id` | Unique identifier | | `session_id` | Session identifier | | `response_content` | Agent's output | | `input_tokens` | Tokens in the prompt | | `output_tokens` | Tokens in the response | | `total_cost_usd` | Total cost in USD | | `duration_ms` | Execution time | | `status` | `completed` or `failed` | ## Statuses | Status | Description | | ----------- | --------------------------- | | `completed` | Agent finished successfully | | `failed` | Agent encountered an error | ## Timeouts Default timeout is **120 seconds** (2 minutes). Maximum timeout: 600 seconds (10 minutes). Timeouts result in a `failed` status with an appropriate error message. ## Cost Tracking Costs are calculated based on: * **Input tokens** — Prompt + system instructions * **Output tokens** — Agent's response * **Model** — Claude pricing tiers View your usage: ```bash theme={null} cast usage ``` ## Concurrency Multiple invocations can run **in parallel**: ```typescript theme={null} // These run concurrently in separate sandboxes const results = await Promise.all([ client.agents.invoke('my-agent', { prompt: 'Task 1' }), client.agents.invoke('my-agent', { prompt: 'Task 2' }), client.agents.invoke('my-agent', { prompt: 'Task 3' }), ]); ``` Each gets its own isolated sandbox. ## Error Handling ### In CLI ```bash theme={null} cast invoke my-agent "Bad request" # Error: Agent execution failed ``` ### In SDK ```typescript theme={null} try { const result = await client.agents.invoke('my-agent', { prompt }); } catch (error) { if (error instanceof CastariError) { console.log(error.status); // 500 console.log(error.message); // "Agent execution failed" } } ``` ## See Also CLI reference SDK reference Troubleshooting tips # Sandboxes Source: https://docs.castari.com/concepts/sandboxes Isolated execution environments for agents # Sandboxes Sandboxes are isolated environments where your agents run. ## What is a Sandbox? A sandbox is a secure, isolated container that: * Runs your agent code * Has its own filesystem * Has network access (egress only) * Is completely isolated from other sandboxes Castari uses [E2B](https://e2b.dev) for sandbox infrastructure. ## Per-Request Sandboxes Every invocation gets a **fresh sandbox**: ``` Request 1 → Sandbox A → Response 1 → Sandbox A destroyed Request 2 → Sandbox B → Response 2 → Sandbox B destroyed Request 3 → Sandbox C → Response 3 → Sandbox C destroyed ``` This provides: * **Security** — No data persists between requests * **Isolation** — One request can't affect another * **Scalability** — Parallel requests run in parallel sandboxes ## Sandbox Lifecycle ### During Deployment 1. New sandbox created 2. Agent code uploaded 3. `npm install` executed 4. Secrets injected as environment variables 5. Sandbox kept warm for invocations ### During Invocation 1. Warm sandbox receives request 2. Agent process started with prompt on stdin 3. Agent executes (Claude + tools) 4. Response captured from stdout 5. Sandbox state reset for next request ### On Redeploy 1. Old sandbox destroyed 2. New sandbox created with updated code 3. All state from old sandbox is lost ## Security Model ### Isolation Each sandbox is a separate container with: * Own filesystem * Own process namespace * Own network namespace * No access to host system ### Network | Direction | Allowed | | ----------------- | ------------------------------- | | Outbound (egress) | Yes — can call external APIs | | Inbound (ingress) | No — cannot receive connections | ### Filesystem * Agents can read/write within their sandbox * No access to other sandboxes * State does not persist between invocations ## Resource Limits | Resource | Default Limit | Notes | | -------- | ------------- | -------------- | | Memory | 2 GB | Per sandbox | | CPU | 2 cores | Shared | | Timeout | 120 seconds | Per invocation | | Disk | 10 GB | Ephemeral | Need higher limits? Contact us for enterprise plans. ## Preinstalled Software Sandboxes come with: * Node.js 20 * npm * git * Common utilities (curl, wget, etc.) ## Debugging Sandbox Issues ### Timeout Errors If your agent times out: 1. Check for infinite loops 2. Optimize slow operations 3. Break complex tasks into smaller steps ### Out of Memory If your agent runs out of memory: 1. Process data in chunks 2. Avoid loading large files entirely into memory 3. Clean up resources after use ### Network Errors If external API calls fail: 1. Check the API is accessible 2. Verify credentials are set as secrets 3. Check for rate limiting ## E2B vs Other Sandboxing Why E2B? | Feature | E2B | Docker | Firecracker | | ------------ | ------ | ------- | ----------- | | Startup time | \~1s | \~5s | \~125ms | | Isolation | Strong | Medium | Strong | | API | Simple | Complex | Complex | | Managed | Yes | No | No | ## See Also Architecture overview Troubleshooting tips # Secrets Source: https://docs.castari.com/concepts/secrets Managing environment variables for agents # Secrets Secrets are environment variables injected into your agent at runtime. ## Why Secrets? Your agents often need access to: * API keys (OpenAI, Stripe, etc.) * Database credentials * Service tokens * Configuration values Secrets let you provide these **securely** without: * Hardcoding in source code * Committing to git * Exposing in logs ## Setting Secrets ### Via CLI ```bash theme={null} cast secrets set my-agent OPENAI_API_KEY sk-abc123... ``` ### Via SDK ```typescript theme={null} await client.secrets.set('my-agent', 'OPENAI_API_KEY', 'sk-abc123...'); ``` ### Interactive Mode Avoid exposing secrets in shell history: ```bash theme={null} cast secrets set my-agent OPENAI_API_KEY # Prompts for value securely ``` ## Using Secrets in Agents Secrets are available as environment variables: ```typescript theme={null} // Access in your agent code const openaiKey = process.env.OPENAI_API_KEY; const databaseUrl = process.env.DATABASE_URL; // Use with OpenAI const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, }); ``` ## Built-in Secrets Castari automatically provides: | Variable | Description | | ------------------- | --------------------------------- | | `ANTHROPIC_API_KEY` | Your Anthropic API key for Claude | You don't need to set `ANTHROPIC_API_KEY` — Castari injects it automatically so your agents can use Claude. ## Secret Storage Secrets are: * **Encrypted at rest** — Using AES-256 * **Never logged** — Values are masked in logs * **Never returned** — API only returns key names, not values * **Scoped per agent** — Each agent has its own secrets ## Listing Secrets ```bash theme={null} cast secrets list my-agent ``` ``` KEY CREATED OPENAI_API_KEY 2024-01-15 10:30:00 DATABASE_URL 2024-01-15 10:30:00 ``` Values are never displayed — only keys and metadata. ## Updating Secrets Set the same key again to update: ```bash theme={null} cast secrets set my-agent OPENAI_API_KEY sk-new-key... ``` Changes take effect on the next invocation. ## Deleting Secrets ```bash theme={null} cast secrets delete my-agent OLD_API_KEY ``` ## Best Practices ### Naming Conventions * Use `UPPERCASE_WITH_UNDERSCORES` * Be descriptive: `STRIPE_SECRET_KEY` not `KEY1` * Prefix by service: `OPENAI_API_KEY`, `STRIPE_API_KEY` ### Security * **Never commit secrets** — Use `.gitignore` for `.env` files * **Rotate regularly** — Update secrets periodically * **Limit scope** — Only set secrets an agent actually needs * **Audit access** — Review who can manage secrets ### Development Keep a `.env.example` file in your repo: ```bash theme={null} # .env.example (committed to git) OPENAI_API_KEY=your-key-here DATABASE_URL=postgres://user:pass@host/db # .env (NOT committed — in .gitignore) OPENAI_API_KEY=sk-actual-key... DATABASE_URL=postgres://actual-connection... ``` ## Secrets in CI/CD Example GitHub Actions workflow: ```yaml theme={null} jobs: deploy: steps: - name: Deploy agent run: cast deploy - name: Set secrets env: CASTARI_API_KEY: ${{ secrets.CASTARI_API_KEY }} run: | cast secrets set my-agent OPENAI_API_KEY "${{ secrets.OPENAI_API_KEY }}" cast secrets set my-agent DATABASE_URL "${{ secrets.DATABASE_URL }}" ``` ## See Also CLI reference SDK reference # Your First Agent Source: https://docs.castari.com/first-agent Understand agent structure and customize your first deployment # Your First Agent After running `cast init`, you have a working agent. Let's understand its structure and how to customize it. ## Agent Structure Every Castari agent has this structure: ``` my-agent/ ├── castari.json # Agent configuration ├── package.json # Dependencies ├── tsconfig.json # TypeScript config ├── src/ │ └── index.ts # Agent entry point ├── CLAUDE.md # Agent instructions └── README.md # Documentation ``` ## castari.json The agent configuration file: ```json theme={null} { "name": "my-agent", "version": "0.1.0", "entrypoint": "src/index.ts", "runtime": "node" } ``` | Field | Description | | ------------ | ---------------------------- | | `name` | Display name for your agent | | `version` | Semantic version | | `entrypoint` | Path to main file | | `runtime` | Runtime environment (`node`) | ## CLAUDE.md This file contains instructions for Claude. It's like a system prompt that shapes your agent's behavior: ```markdown theme={null} # My Agent You are a helpful coding assistant. ## Guidelines - Be concise and direct - Always explain before making changes - Ask for clarification when requirements are unclear ## Tools Available - `read_file` - Read file contents - `write_file` - Create or update files - `bash` - Run shell commands ``` The better your CLAUDE.md, the better your agent performs. Be specific about capabilities, constraints, and expected behavior. ## src/index.ts The entry point defines your agent's tools and handles invocations: ```typescript theme={null} import Anthropic from "@anthropic-ai/sdk"; const client = new Anthropic(); // Define tools const tools: Anthropic.Tool[] = [ { name: "read_file", description: "Read the contents of a file", input_schema: { type: "object", properties: { path: { type: "string", description: "File path to read" } }, required: ["path"] } }, // ... more tools ]; // Handle tool calls async function handleTool(name: string, input: any): Promise { switch (name) { case "read_file": return fs.readFileSync(input.path, "utf-8"); // ... handle other tools } } // Main agent loop async function run(prompt: string) { // Agent implementation } // Read prompt from stdin, run agent, output to stdout let prompt = ""; process.stdin.on("data", (chunk) => (prompt += chunk)); process.stdin.on("end", async () => { const response = await run(prompt); console.log(response); }); ``` ## Local Testing Test your agent locally before deploying: ```bash theme={null} cd my-agent echo "What files are here?" | npm run dev ``` This runs your agent with the prompt as input, just like `cast invoke` does remotely. ## Customizing Your Agent ### Add a New Tool 1. Define the tool schema in `tools` array 2. Add the handler in `handleTool` function ```typescript theme={null} // 1. Define the tool { name: "search_web", description: "Search the web for information", input_schema: { type: "object", properties: { query: { type: "string", description: "Search query" } }, required: ["query"] } } // 2. Handle the tool case "search_web": return await searchWeb(input.query); ``` ### Change Agent Behavior Edit `CLAUDE.md` to change how your agent thinks and acts: ```markdown theme={null} # Research Agent You are a research assistant that finds and synthesizes information. ## Guidelines - Always cite sources - Present multiple perspectives - Summarize findings at the end ``` ### Add Dependencies ```bash theme={null} npm install axios # Example: HTTP client ``` Then import and use in your agent: ```typescript theme={null} import axios from 'axios'; // In your tool handler const response = await axios.get('https://api.example.com/data'); ``` ## Redeploying After making changes, redeploy: ```bash theme={null} cast deploy ``` This uploads your changes and creates a fresh sandbox. Redeploying destroys the previous sandbox. Any files or state in the sandbox are lost. ## Next Steps Learn all available commands Try different agent templates Add API keys for external services Understand the architecture # Best Practices Source: https://docs.castari.com/guides/best-practices Guidelines for building production-ready agents # Best Practices Guidelines for building reliable, secure, and efficient agents. ## Agent Design ### Keep Tools Focused Each tool should do one thing well: ```typescript theme={null} // Good: Specific, focused tools { name: "read_file", description: "Read file contents" } { name: "write_file", description: "Write content to file" } { name: "list_files", description: "List files in directory" } // Bad: One tool that does everything { name: "file_operations", description: "Read, write, delete, list files" } ``` ### Write Clear Tool Descriptions Claude uses descriptions to decide when to use tools: ```typescript theme={null} // Good: Clear, specific description { name: "search_users", description: "Search for users by email address. Returns matching user profiles with id, name, and email." } // Bad: Vague description { name: "search_users", description: "Search users" } ``` ### Use CLAUDE.md Effectively Structure your CLAUDE.md for clarity: ```markdown theme={null} # Agent Name One-line description of what this agent does. ## Capabilities - What the agent CAN do - Available tools and their purposes ## Limitations - What the agent should NOT do - Boundaries and restrictions ## Guidelines - How to approach tasks - Tone and communication style - When to ask for clarification ## Examples - Example inputs and expected behavior ``` ## Error Handling ### Handle Tool Failures Gracefully ```typescript theme={null} try { const result = await executeTool(toolUse.name, toolUse.input); toolResults.push({ type: "tool_result", tool_use_id: toolUse.id, content: result }); } catch (error) { // Return error as tool result so Claude can adapt toolResults.push({ type: "tool_result", tool_use_id: toolUse.id, content: `Error: ${error.message}`, is_error: true }); } ``` ### Validate Inputs ```typescript theme={null} case "read_file": // Validate path exists if (!input.path) { throw new Error("path is required"); } // Validate path is safe if (input.path.includes("..")) { throw new Error("path traversal not allowed"); } // Check file exists if (!fs.existsSync(input.path)) { throw new Error(`file not found: ${input.path}`); } return fs.readFileSync(input.path, "utf-8"); ``` ### Set Timeouts ```typescript theme={null} const timeout = (ms: number) => new Promise((_, reject) => setTimeout(() => reject(new Error(`Timeout after ${ms}ms`)), ms) ); // Wrap long operations const result = await Promise.race([ executeSlowOperation(), timeout(30000) ]); ``` ## Security ### Never Trust User Input ```typescript theme={null} // Bad: SQL injection risk case "query_database": return db.query(input.query); // Good: Parameterized queries only case "query_database": return db.query(input.query, input.params); ``` ### Restrict File Access ```typescript theme={null} const ALLOWED_PATHS = ['/workspace', '/tmp']; function isPathAllowed(filePath: string): boolean { const resolved = path.resolve(filePath); return ALLOWED_PATHS.some(allowed => resolved.startsWith(allowed) ); } case "read_file": if (!isPathAllowed(input.path)) { throw new Error("Access denied"); } return fs.readFileSync(input.path, "utf-8"); ``` ### Sanitize Command Execution ```typescript theme={null} // Bad: Command injection risk case "bash": return execSync(input.command); // Better: Whitelist safe commands const ALLOWED_COMMANDS = ['ls', 'cat', 'grep', 'find']; case "bash": const cmd = input.command.split(' ')[0]; if (!ALLOWED_COMMANDS.includes(cmd)) { throw new Error(`Command not allowed: ${cmd}`); } return execSync(input.command); ``` ### Use Secrets for Credentials ```typescript theme={null} // Bad: Hardcoded credentials const apiKey = "sk-abc123"; // Good: Use environment variables const apiKey = process.env.API_KEY; if (!apiKey) { throw new Error("API_KEY not configured"); } ``` ## Performance ### Minimize API Calls ```typescript theme={null} // Bad: Multiple calls for same data const user = await getUser(id); const orders = await getOrders(id); const preferences = await getPreferences(id); // Better: Batch or cache const userData = await getUserWithDetails(id); // or use caching ``` ### Stream Large Outputs For long responses, consider streaming: ```typescript theme={null} // Instead of buffering everything let output = ""; for (const chunk of results) { output += chunk; } console.log(output); // Stream incrementally for (const chunk of results) { process.stdout.write(chunk); } ``` ### Clean Up Resources ```typescript theme={null} // Close connections when done const pool = new Pool({ connectionString: process.env.DATABASE_URL }); process.on('exit', () => { pool.end(); }); ``` ## Testing ### Test Locally First ```bash theme={null} # Test with various inputs echo "Simple prompt" | npm run dev echo "What files are here?" | npm run dev echo "Create a file called test.txt" | npm run dev ``` ### Test Edge Cases * Empty prompts * Very long prompts * Prompts that might cause infinite loops * Prompts with special characters ### Test Tool Failures ```bash theme={null} echo "Read /nonexistent/file.txt" | npm run dev # Should handle gracefully, not crash ``` ## Monitoring ### Log Important Events ```typescript theme={null} console.error(`[${new Date().toISOString()}] Agent started`); console.error(`[${new Date().toISOString()}] Tool: ${name}`); console.error(`[${new Date().toISOString()}] Tokens: ${inputTokens}/${outputTokens}`); ``` ### Track Costs Monitor your usage: ```bash theme={null} cast usage cast usage --daily ``` ## Deployment ### Use Git for Versioning Keep your agent in version control: ```bash theme={null} git init git add . git commit -m "Initial agent" ``` ### Document Your Agent Include a README.md: ```markdown theme={null} # My Agent Description of what this agent does. ## Setup 1. `npm install` 2. Configure secrets: `cast secrets set my-agent API_KEY xxx` 3. Deploy: `cast deploy` ## Usage cast invoke my-agent "Your prompt here" ## Development npm run dev ``` ## See Also Troubleshooting tips Managing credentials # Claude Code Plugin Source: https://docs.castari.com/guides/claude-code Deploy agents to Castari directly from Claude Code # Claude Code Plugin The Castari plugin for [Claude Code](https://claude.ai/code) lets you deploy agents without leaving your editor. Type `/castari-deploy` and the skill handles CLI installation, authentication, project scaffolding, and deployment — all in one flow. **View on skills.sh:** [skills.sh/castari/cli](https://skills.sh/castari/cli) ## Install the Plugin ```bash theme={null} npx skills add castari/cli ``` This installs the Castari plugin into your Claude Code environment. Once installed, the `/castari-deploy` skill is available in any project. ## Using `/castari-deploy` Type `/castari-deploy` in Claude Code (or ask Claude to "deploy to Castari") and the skill walks through the full deployment flow: ### Step 1: CLI Check The skill checks if the Castari CLI is installed by running `cast --version`. If not found, it installs the CLI globally via npm. ### Step 2: Authentication Runs `cast whoami` to check if you're logged in. If not, it triggers `cast login` which opens your browser for Clerk OAuth authentication. ### Step 3: Project Configuration Looks for `castari.json` in your project root. If one exists, the skill confirms its configuration with you. If not, it: * Detects your entrypoint file (e.g., `src/index.ts`, `index.js`) * Asks you for an agent name * Generates a `castari.json` manifest ### Step 4: Deploy Runs `cast deploy` to package your project and deploy it to an isolated cloud sandbox. ### Step 5: Verification Shows you a summary of the deployment — agent name, status, and sandbox ID. ### Step 6: Testing Offers to test the deployed agent by running `cast invoke` with a prompt you provide. ## Trigger Phrases The skill activates when you ask Claude to: * "deploy to Castari" * "deploy my agent" * "castari deploy" * "push agent to Castari" * "ship my agent" * "set up Castari" Or any variation of deploying an agent to Castari. ## Requirements * [Node.js](https://nodejs.org) 18 or higher * A [Castari account](https://app.castari.com) (free to sign up) * [Claude Code](https://claude.ai/code) installed ## See Also Manual deployment walkthrough Full CLI command reference Building agents from scratch Start from a template # Building Custom Agents Source: https://docs.castari.com/guides/custom-agents Build agents from scratch with the Claude Agent SDK # Building Custom Agents Learn how to build agents from scratch using the Claude Agent SDK. ## Prerequisites * Node.js 18+ * Castari CLI installed (`npm install -g @castari/cli`) * Basic TypeScript knowledge ## Agent Architecture A Castari agent is a Node.js program that: 1. Reads a prompt from **stdin** 2. Processes with **Claude** and executes **tools** 3. Writes response to **stdout** ``` stdin (prompt) → Agent (Claude + Tools) → stdout (response) ``` ## Creating an Agent from Scratch ### 1. Initialize the Project ```bash theme={null} mkdir my-custom-agent cd my-custom-agent npm init -y npm install @anthropic-ai/sdk typescript tsx ``` ### 2. Create castari.json ```json theme={null} { "name": "my-custom-agent", "version": "0.1.0", "entrypoint": "src/index.ts", "runtime": "node" } ``` ### 3. Create package.json Scripts ```json theme={null} { "scripts": { "dev": "tsx src/index.ts", "build": "tsc" } } ``` ### 4. Write the Agent ```typescript theme={null} // src/index.ts import Anthropic from "@anthropic-ai/sdk"; import * as fs from "fs"; import { execSync } from "child_process"; const client = new Anthropic(); // Read CLAUDE.md for system instructions const systemPrompt = fs.existsSync("CLAUDE.md") ? fs.readFileSync("CLAUDE.md", "utf-8") : "You are a helpful assistant."; // Define tools const tools: Anthropic.Tool[] = [ { name: "read_file", description: "Read the contents of a file", input_schema: { type: "object", properties: { path: { type: "string", description: "Path to the file" } }, required: ["path"] } }, { name: "write_file", description: "Write content to a file", input_schema: { type: "object", properties: { path: { type: "string", description: "Path to the file" }, content: { type: "string", description: "Content to write" } }, required: ["path", "content"] } }, { name: "bash", description: "Execute a bash command", input_schema: { type: "object", properties: { command: { type: "string", description: "Command to execute" } }, required: ["command"] } } ]; // Handle tool execution async function executeTool(name: string, input: any): Promise { switch (name) { case "read_file": return fs.readFileSync(input.path, "utf-8"); case "write_file": fs.writeFileSync(input.path, input.content); return `Wrote ${input.content.length} bytes to ${input.path}`; case "bash": return execSync(input.command, { encoding: "utf-8" }); default: throw new Error(`Unknown tool: ${name}`); } } // Agent loop async function runAgent(prompt: string): Promise { const messages: Anthropic.MessageParam[] = [ { role: "user", content: prompt } ]; while (true) { const response = await client.messages.create({ model: "claude-sonnet-4-20250514", max_tokens: 4096, system: systemPrompt, tools, messages }); // Collect text and tool uses let textResponse = ""; const toolUses: Anthropic.ToolUseBlock[] = []; for (const block of response.content) { if (block.type === "text") { textResponse += block.text; } else if (block.type === "tool_use") { toolUses.push(block); } } // If no tool uses, we're done if (toolUses.length === 0) { return textResponse; } // Execute tools and continue messages.push({ role: "assistant", content: response.content }); const toolResults: Anthropic.ToolResultBlockParam[] = []; for (const toolUse of toolUses) { try { const result = await executeTool(toolUse.name, toolUse.input); toolResults.push({ type: "tool_result", tool_use_id: toolUse.id, content: result }); } catch (error) { toolResults.push({ type: "tool_result", tool_use_id: toolUse.id, content: `Error: ${error.message}`, is_error: true }); } } messages.push({ role: "user", content: toolResults }); } } // Entry point: read from stdin, write to stdout async function main() { let prompt = ""; for await (const chunk of process.stdin) { prompt += chunk; } const response = await runAgent(prompt.trim()); console.log(response); } main().catch(console.error); ``` ### 5. Create CLAUDE.md ```markdown theme={null} # My Custom Agent You are a helpful coding assistant. ## Capabilities - Read and write files - Execute bash commands - Help with coding tasks ## Guidelines - Be concise and direct - Always explain what you're about to do - Ask for clarification when requirements are unclear ``` ### 6. Test Locally ```bash theme={null} echo "What files are in the current directory?" | npm run dev ``` ### 7. Deploy ```bash theme={null} cast deploy ``` ## Adding Custom Tools ### Tool Schema Tools are defined with JSON Schema: ```typescript theme={null} { name: "get_weather", description: "Get weather for a location", input_schema: { type: "object", properties: { location: { type: "string", description: "City name" }, units: { type: "string", enum: ["celsius", "fahrenheit"], description: "Temperature units" } }, required: ["location"] } } ``` ### Tool Handler ```typescript theme={null} case "get_weather": const weather = await fetchWeather(input.location, input.units); return JSON.stringify(weather); ``` ### External API Integration ```typescript theme={null} import axios from 'axios'; case "get_weather": const response = await axios.get( `https://api.weather.com/v1/current`, { params: { q: input.location }, headers: { 'X-API-Key': process.env.WEATHER_API_KEY } } ); return JSON.stringify(response.data); ``` Don't forget to set the secret: ```bash theme={null} cast secrets set my-agent WEATHER_API_KEY your-key-here ``` ## Best Practices ### Error Handling Always handle tool errors gracefully: ```typescript theme={null} try { const result = await executeTool(toolUse.name, toolUse.input); toolResults.push({ type: "tool_result", tool_use_id: toolUse.id, content: result }); } catch (error) { toolResults.push({ type: "tool_result", tool_use_id: toolUse.id, content: `Error: ${error.message}`, is_error: true }); } ``` ### Timeout Handling For long-running operations: ```typescript theme={null} const timeout = (ms: number) => new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), ms) ); const result = await Promise.race([ executeTool(name, input), timeout(30000) // 30 second timeout ]); ``` ### Logging Write debug info to stderr (doesn't affect response): ```typescript theme={null} console.error(`[DEBUG] Executing tool: ${name}`); console.error(`[DEBUG] Input: ${JSON.stringify(input)}`); ``` ## See Also Start with pre-built agents Model Context Protocol tools Troubleshooting tips # Debugging Agents Source: https://docs.castari.com/guides/debugging Troubleshooting tips and common issues # Debugging Agents When things go wrong, here's how to diagnose and fix them. ## Local Testing Always test locally before deploying: ```bash theme={null} cd my-agent echo "What files are here?" | npm run dev ``` This runs your agent exactly as Castari does — prompt on stdin, response on stdout. ### Debug Mode Add debug output to stderr (doesn't affect response): ```typescript theme={null} console.error('[DEBUG] Starting agent...'); console.error(`[DEBUG] Prompt: ${prompt}`); console.error(`[DEBUG] Executing tool: ${toolName}`); ``` ## Common Errors ### "Agent not found" **Cause:** Wrong slug or agent doesn't exist. **Fix:** ```bash theme={null} cast agents list # See correct slugs cast invoke correct-slug "Hello" ``` ### "Agent not active" **Cause:** Agent isn't deployed or was stopped. **Fix:** ```bash theme={null} cast agents get my-agent # Check status cast deploy # Redeploy ``` ### "castari.json not found" **Cause:** Missing configuration file. **Fix:** Create `castari.json` in your agent root: ```json theme={null} { "name": "my-agent", "version": "0.1.0", "entrypoint": "src/index.ts", "runtime": "node" } ``` ### "npm install failed" **Cause:** Dependency issues. **Fix:** 1. Run `npm install` locally first 2. Check `package.json` for errors 3. Ensure all packages are published to npm ### "Timeout exceeded" **Cause:** Agent took too long (>120s default). **Fix:** * Optimize slow operations * Break complex tasks into smaller steps * Check for infinite loops ### "Tool execution failed" **Cause:** Error in tool handler. **Fix:** ```typescript theme={null} // Add error handling case "my_tool": try { return await executeTool(input); } catch (error) { console.error(`[ERROR] Tool failed: ${error.message}`); throw error; } ``` ### "ANTHROPIC\_API\_KEY not set" **Cause:** Missing API key. **Fix:** Castari injects this automatically. If you see this locally: ```bash theme={null} export ANTHROPIC_API_KEY=your-key echo "Hello" | npm run dev ``` ## Debugging Tool Calls ### Log Tool Inputs/Outputs ```typescript theme={null} async function executeTool(name: string, input: any): Promise { console.error(`[TOOL] ${name} called with:`, JSON.stringify(input)); const result = await doToolWork(name, input); console.error(`[TOOL] ${name} returned:`, result.substring(0, 100)); return result; } ``` ### Validate Tool Schemas Ensure your tool schemas match what Claude sends: ```typescript theme={null} // Schema says required: ["path"] // Make sure you handle missing path case "read_file": if (!input.path) { throw new Error("path is required"); } return fs.readFileSync(input.path, "utf-8"); ``` ## Debugging Claude Interactions ### Log Messages ```typescript theme={null} async function runAgent(prompt: string) { const messages = [{ role: "user", content: prompt }]; while (true) { console.error(`[CLAUDE] Sending ${messages.length} messages`); const response = await client.messages.create({ model: "claude-sonnet-4-20250514", messages, tools }); console.error(`[CLAUDE] Stop reason: ${response.stop_reason}`); console.error(`[CLAUDE] Content blocks: ${response.content.length}`); // ... rest of loop } } ``` ### Check Stop Reasons | Stop Reason | Meaning | | --------------- | -------------------------- | | `end_turn` | Claude finished responding | | `tool_use` | Claude wants to use a tool | | `max_tokens` | Hit token limit | | `stop_sequence` | Hit a stop sequence | ## Environment Issues ### Check Secrets ```bash theme={null} cast secrets list my-agent ``` Make sure required secrets are set. ### Check Agent Status ```bash theme={null} cast agents get my-agent ``` ``` Name: My Agent Slug: my-agent Status: active Sandbox ID: sbx_xyz789 ``` If status is `error`, redeploy: ```bash theme={null} cast deploy ``` ## Getting Help If you're stuck: 1. **Test locally:** `echo "prompt" | npm run dev` 2. **Check status:** `cast agents get my-agent` 3. **Redeploy:** `cast deploy` Still stuck? Open an issue on [GitHub](https://github.com/castari/cli). ## See Also Execution environment CLI reference # Working with Files Source: https://docs.castari.com/guides/files Upload and attach files to agents # Working with Files This guide covers how to provide files to your agents using Castari's managed file storage. ## Quick Start ```bash theme={null} # Upload a file cast files upload data.csv # Attach to agent cast agents files add my-agent file_abc123 # Deploy agent cast deploy my-agent ``` Your agent can now read the file at `/files/agent/data.csv`. ## Uploading Files ### CLI Upload ```bash theme={null} # Basic upload cast files upload myfile.json # With metadata cast files upload data.csv --description "Customer data" --tags sales,2024 ``` ### Dashboard Upload 1. Go to **Files** in the sidebar 2. Click **Upload File** 3. Drag & drop or select a file 4. Add optional description and tags 5. Click **Upload** ### Large Files Files larger than 10MB automatically use presigned uploads: ```bash theme={null} # Large file upload (handled automatically) cast files upload large-dataset.parquet ``` The CLI shows progress for large uploads: ``` Uploading large-dataset.parquet (150 MB)... ████████████████████████████░░░░░░░░░░░░ 70% ``` ## Attaching Files to Agents ### Basic Attachment ```bash theme={null} cast agents files add my-agent file_abc123 ``` The file appears at `/files/agent/` in the sandbox. ### Custom Mount Path ```bash theme={null} cast agents files add my-agent file_abc123 --mount-path /data/custom.csv ``` ### Writable Files By default, files are read-only. For writable files: ```bash theme={null} cast agents files add my-agent file_abc123 --writable ``` Writable files can be modified by the agent. Use with caution. ## Using Files in Agent Code ### Reading Files ```typescript theme={null} import { readFileSync, readFile } from 'fs'; import { readFile as asyncReadFile } from 'fs/promises'; // Synchronous read const data = readFileSync('/files/agent/data.csv', 'utf-8'); // Async read const asyncData = await asyncReadFile('/files/agent/data.csv', 'utf-8'); ``` ### Parsing Common Formats **CSV:** ```typescript theme={null} import { parse } from 'csv-parse/sync'; const csvContent = readFileSync('/files/agent/data.csv', 'utf-8'); const records = parse(csvContent, { columns: true }); ``` **JSON:** ```typescript theme={null} const config = JSON.parse( readFileSync('/files/agent/config.json', 'utf-8') ); ``` ### Checking File Existence ```typescript theme={null} import { existsSync } from 'fs'; if (existsSync('/files/agent/optional.txt')) { // File is available } ``` ## Managing Files ### List Your Files ```bash theme={null} # List all files cast files list # Filter by tags cast files list --tags dataset # Search by name cast files list --search training ``` ### View File Details ```bash theme={null} cast files get file_abc123 ``` ### Delete Files ```bash theme={null} cast files delete file_abc123 ``` Deleting a file automatically detaches it from all agents. ### Download Files ```bash theme={null} cast files download file_abc123 --output ./local-copy.csv ``` ## Agent File Management ### List Attached Files ```bash theme={null} cast agents files list my-agent ``` ``` File ID Filename Mount Path Size Mode file_abc123 data.csv /files/agent/data.csv 2.4 MB ro file_def456 config.json /files/agent/config.json 1.2 KB ro ``` ### Detach Files ```bash theme={null} cast agents files remove my-agent file_abc123 ``` ## Dashboard File Management ### Files Page The **Files** page shows: * All your uploaded files * Storage usage bar * Quick search and filtering ### Agent Files Section Each agent's detail page has an **Attached Files** section: * View attached files and mount paths * Attach new files with the file picker * Detach files you no longer need ## Storage Usage ### Check Your Quota ```bash theme={null} cast files usage ``` ``` Total Files 12 Total Size 45.2 MB Quota Used 45.2% Quota Limit 100 MB ``` ### Storage Limits | Plan | Limit | | ---------- | ------ | | Free | 100 MB | | Pro | 10 GB | | Enterprise | Custom | ## Best Practices ### File Organization 1. **Use meaningful names** — `customer-data-2024.csv` not `data.csv` 2. **Add descriptions** — Document what each file is for 3. **Tag consistently** — Use tags like `dataset`, `config`, `reference` 4. **Clean up unused files** — Delete files you no longer need ### Performance 1. **Keep files reasonably sized** — Under 100MB for best performance 2. **Use appropriate formats** — CSV/JSON for structured data 3. **Consider streaming** — For very large files, process in chunks ### Security 1. **Don't upload secrets** — Use [Secrets](/concepts/secrets) for credentials 2. **Review before attaching** — Only attach files agents actually need 3. **Verify file integrity** — Check SHA256 hash for critical files ## Common Patterns ### Configuration Files ```bash theme={null} # Upload config cast files upload agent-config.json --tags config # Attach to agent cast agents files add my-agent file_abc123 ``` ```typescript theme={null} // In agent code const config = JSON.parse( readFileSync('/files/agent/agent-config.json', 'utf-8') ); ``` ### Data Processing ```bash theme={null} # Upload dataset cast files upload training-data.csv --tags dataset,ml # Attach cast agents files add ml-agent file_abc123 ``` ```typescript theme={null} // In agent code import { parse } from 'csv-parse/sync'; const csv = readFileSync('/files/agent/training-data.csv', 'utf-8'); const data = parse(csv, { columns: true }); // Process data... ``` ### Reference Documents ```bash theme={null} # Upload reference material cast files upload product-docs.txt --tags reference,docs # Attach cast agents files add support-agent file_abc123 ``` ```typescript theme={null} // In agent code const docs = readFileSync('/files/agent/product-docs.txt', 'utf-8'); // Use in system prompt or for RAG ``` ## Troubleshooting ### File Not Found If your agent can't find a file: 1. Verify the file is attached: ```bash theme={null} cast agents files list my-agent ``` 2. Check the mount path in the output 3. Ensure you're using the correct path in code ### Upload Failures For upload issues: 1. Check your storage quota: ```bash theme={null} cast files usage ``` 2. Verify the file exists locally 3. For large files, ensure stable network connection ### Permission Errors If you get permission errors: 1. Files are read-only by default 2. Use `--writable` when attaching if writes are needed 3. Check file mode in `cast agents files list` ## See Also * [Managed Files Concept](/concepts/files) — How file storage works * [cast files](/cli/files) — CLI reference * [Storage Buckets](/guides/storage) — BYO storage for large datasets # MCP Integration Source: https://docs.castari.com/guides/mcp Using Model Context Protocol tools with agents # MCP Integration The Model Context Protocol (MCP) provides a standardized way to give Claude access to external tools and data sources. ## What is MCP? MCP is an open protocol that lets you connect Claude to: * **Databases** — Query and update data * **APIs** — Call external services * **File systems** — Read and write files * **Custom tools** — Any functionality you define ## MCP vs Built-in Tools | Approach | Use When | | -------------- | -------------------------------------------- | | Built-in tools | Simple, self-contained tools | | MCP servers | Complex integrations, reusable across agents | ## Using MCP in Castari Agents ### 1. Install MCP SDK ```bash theme={null} npm install @modelcontextprotocol/sdk ``` ### 2. Define MCP Tools ```typescript theme={null} import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; const server = new Server( { name: "my-tools", version: "1.0.0" }, { capabilities: { tools: {} } } ); // Define a tool server.setRequestHandler("tools/list", async () => ({ tools: [ { name: "query_database", description: "Query the database", inputSchema: { type: "object", properties: { query: { type: "string", description: "SQL query" } }, required: ["query"] } } ] })); // Handle tool calls server.setRequestHandler("tools/call", async (request) => { const { name, arguments: args } = request.params; if (name === "query_database") { const results = await executeQuery(args.query); return { content: [{ type: "text", text: JSON.stringify(results) }] }; } }); ``` ### 3. Connect to Claude ```typescript theme={null} import Anthropic from "@anthropic-ai/sdk"; import { Client } from "@modelcontextprotocol/sdk/client/index.js"; const client = new Anthropic(); const mcpClient = new Client({ name: "agent", version: "1.0.0" }); // Get tools from MCP server const tools = await mcpClient.listTools(); // Use with Claude const response = await client.messages.create({ model: "claude-sonnet-4-20250514", tools: tools.tools.map(t => ({ name: t.name, description: t.description, input_schema: t.inputSchema })), messages: [{ role: "user", content: prompt }] }); // Execute tool calls via MCP for (const block of response.content) { if (block.type === "tool_use") { const result = await mcpClient.callTool({ name: block.name, arguments: block.input }); } } ``` ## Example: Database Agent A complete example integrating with PostgreSQL: ```typescript theme={null} // src/tools/database.ts import { Pool } from 'pg'; const pool = new Pool({ connectionString: process.env.DATABASE_URL }); export const databaseTools: Anthropic.Tool[] = [ { name: "query_database", description: "Execute a read-only SQL query", input_schema: { type: "object", properties: { query: { type: "string", description: "SQL SELECT query" } }, required: ["query"] } }, { name: "list_tables", description: "List all tables in the database", input_schema: { type: "object", properties: {} } } ]; export async function executeDatabaseTool( name: string, input: any ): Promise { switch (name) { case "query_database": // Safety: only allow SELECT queries if (!input.query.trim().toLowerCase().startsWith("select")) { throw new Error("Only SELECT queries are allowed"); } const result = await pool.query(input.query); return JSON.stringify(result.rows, null, 2); case "list_tables": const tables = await pool.query(` SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' `); return tables.rows.map(r => r.table_name).join("\n"); default: throw new Error(`Unknown tool: ${name}`); } } ``` Set the secret: ```bash theme={null} cast secrets set my-agent DATABASE_URL postgres://user:pass@host/db ``` ## Example: API Integration Integrating with an external REST API: ```typescript theme={null} // src/tools/api.ts import axios from 'axios'; export const apiTools: Anthropic.Tool[] = [ { name: "get_user", description: "Get user details by ID", input_schema: { type: "object", properties: { user_id: { type: "string" } }, required: ["user_id"] } }, { name: "create_ticket", description: "Create a support ticket", input_schema: { type: "object", properties: { subject: { type: "string" }, description: { type: "string" }, priority: { type: "string", enum: ["low", "medium", "high"] } }, required: ["subject", "description"] } } ]; const api = axios.create({ baseURL: 'https://api.example.com', headers: { 'Authorization': `Bearer ${process.env.API_TOKEN}` } }); export async function executeApiTool(name: string, input: any): Promise { switch (name) { case "get_user": const user = await api.get(`/users/${input.user_id}`); return JSON.stringify(user.data); case "create_ticket": const ticket = await api.post('/tickets', input); return `Created ticket #${ticket.data.id}`; default: throw new Error(`Unknown tool: ${name}`); } } ``` ## Best Practices ### Security 1. **Validate inputs** — Never pass raw user input to databases or APIs 2. **Limit scope** — Only expose necessary operations 3. **Use secrets** — Never hardcode credentials ### Performance 1. **Connection pooling** — Reuse database connections 2. **Timeouts** — Set reasonable timeouts for external calls 3. **Caching** — Cache frequently accessed data ### Error Handling ```typescript theme={null} try { const result = await executeApiTool(name, input); return result; } catch (error) { if (axios.isAxiosError(error)) { return `API Error: ${error.response?.status} - ${error.response?.data?.message}`; } throw error; } ``` ## See Also Building agents from scratch Managing credentials # Using Templates Source: https://docs.castari.com/guides/templates Start with pre-built agent templates # Using Templates Templates give you a working agent in seconds. Start from a proven foundation, then customize. ## Available Templates | Template | Description | Best For | | ---------------- | --------------------------------- | ----------------------------- | | `default` | Coding agent with file/bash tools | General purpose, coding tasks | | `research-agent` | Web search and document synthesis | Research, reports, analysis | | `support-agent` | Ticket handling and escalation | Customer support workflows | | `mcp-tools` | Custom tool integration example | Learning MCP patterns | ## Using cast init ```bash theme={null} cast init my-agent ``` Interactive prompt: ``` ? Select a template: ❯ default — Coding agent with file and bash tools (like Claude Code) research-agent — Deep research with web search and document synthesis support-agent — Customer support with ticket handling and escalation mcp-tools — Agent with example MCP server integration ``` ### Skip the prompt ```bash theme={null} cast init my-agent --template research-agent ``` ## Template Structure Every template includes: ``` my-agent/ ├── castari.json # Agent configuration ├── package.json # Dependencies ├── tsconfig.json # TypeScript config ├── src/ │ └── index.ts # Agent entry point with tools ├── CLAUDE.md # Agent instructions └── README.md # Documentation ``` *** ## Template: default A Claude Code-style agent with file and bash tools. **Tools included:** | Tool | Description | | ------------ | ----------------------- | | `read_file` | Read file contents | | `write_file` | Create/update files | | `bash` | Execute shell commands | | `list_files` | List directory contents | **Example invocations:** ```bash theme={null} cast invoke my-agent "What files are here?" cast invoke my-agent "Create a hello.py that prints Hello World" cast invoke my-agent "Run the tests" ``` **Best for:** General-purpose coding assistance, file manipulation, automation. *** ## Template: research-agent Deep research with web search and document synthesis. **Tools included:** | Tool | Description | | ------------- | ------------------------ | | `web_search` | Search the web | | `read_url` | Fetch and read web pages | | `save_report` | Save findings to file | | `read_file` | Read local documents | **Example invocations:** ```bash theme={null} cast invoke my-agent "Research the current state of AI agents in 2026" cast invoke my-agent "Compare AWS, GCP, and Azure for serverless" ``` The research-agent template includes a mock web search. For production, integrate with SerpAPI, Tavily, or similar. **Best for:** Research tasks, report generation, competitive analysis. *** ## Template: support-agent Customer support with ticket handling. **Tools included:** | Tool | Description | | --------------- | --------------------- | | `lookup_user` | Find user by email/ID | | `lookup_order` | Find order details | | `create_ticket` | Escalate to human | | `send_response` | Reply to customer | **Example invocations:** ```bash theme={null} cast invoke my-agent "I need help with order #12345" cast invoke my-agent "How do I reset my password?" ``` **Best for:** Customer support automation, help desk, FAQ handling. *** ## Template: mcp-tools Example of custom MCP tool integration. **Tools included:** | Tool | Description | | ------------------- | ----------------------- | | `calculate` | Math calculations | | `get_weather` | Weather lookup (mock) | | `query_database` | Database queries (mock) | | `send_notification` | Send alerts | **Use this to learn:** * How to define tool schemas * How to implement tool handlers * How to integrate external services **Best for:** Learning tool development, prototyping custom integrations. *** ## Customizing Templates ### 1. Edit CLAUDE.md The `CLAUDE.md` file contains agent instructions: ```markdown theme={null} # My Agent You are a helpful assistant that... ## Guidelines - Be concise - Always explain before acting - Ask for clarification when unsure ``` ### 2. Modify Tools Edit `src/index.ts` to add, remove, or modify tools: ```typescript theme={null} const tools: Anthropic.Tool[] = [ { name: "my_custom_tool", description: "Does something useful", input_schema: { type: "object", properties: { input: { type: "string" } }, required: ["input"] } } ]; ``` ### 3. Add Dependencies ```bash theme={null} npm install axios # Example: add HTTP client ``` Then use in your agent: ```typescript theme={null} import axios from 'axios'; // In your tool handler const response = await axios.get('https://api.example.com/data'); ``` ### 4. Redeploy After changes: ```bash theme={null} cast deploy ``` ## See Also Build from scratch Advanced tool patterns # Introduction Source: https://docs.castari.com/index Deploy Claude agents with one command Castari # Castari **Deploy Claude agents with one command.** Castari is the natural runtime for AI agents. We deploy your Claude agents in secure, auto-scaling sandboxes — so you go from prototype to production in minutes, not weeks. Deploy your first agent in under 5 minutes All commands at your fingertips Build programmatically with TypeScript Direct REST API access **Using Claude Code?** Type `/castari-deploy` and deploy your agent without leaving the editor. Install the plugin with `npx skills add castari/cli`. [Get started →](/guides/claude-code) ## How It Works ```bash theme={null} # 1. Install npm install -g @castari/cli # 2. Login cast login # 3. Create an agent cast init my-agent # 4. Deploy cd my-agent && cast deploy # 5. Invoke cast invoke my-agent "Hello!" ``` That's it. Your agent is now running in a secure sandbox, ready to scale. ## Why Castari? Deploy in seconds, not hours. No infrastructure to manage. Every agent runs in an isolated sandbox. Your code, your data, protected. Per-request scaling. Fresh sandbox for every invocation. Pay for what you use. ## What You Can Build * **Coding agents** — Review code, write scripts, analyze repos * **Research agents** — Search the web, synthesize findings, generate reports * **Support agents** — Handle tickets, look up data, escalate issues * **Custom agents** — Any Claude-powered workflow with tools ## Get Started Deploy your first agent in under 5 minutes # Installation Source: https://docs.castari.com/installation Install the Castari CLI and SDK # Installation Install the Castari CLI to deploy and manage agents from your terminal. ## CLI Installation ```bash theme={null} npm install -g @castari/cli ``` ```bash theme={null} yarn global add @castari/cli ``` ```bash theme={null} pnpm add -g @castari/cli ``` ### Verify Installation ```bash theme={null} cast --version ``` **Using Claude Code?** Install the [Castari plugin](https://skills.sh/castari/cli) with `npx skills add castari/cli` and type `/castari-deploy` to handle installation, auth, and deployment in one step. [Learn more](/guides/claude-code). You should see output like: ``` @castari/cli/0.1.0 ``` ## SDK Installation If you want to use Castari programmatically (e.g., in a Node.js app or CI/CD pipeline): ```bash theme={null} npm install @castari/sdk ``` ```bash theme={null} yarn add @castari/sdk ``` ```bash theme={null} pnpm add @castari/sdk ``` ## System Requirements | Requirement | Version | | ---------------- | --------------------- | | Node.js | 18.0 or higher | | npm | 8.0 or higher | | Operating System | macOS, Linux, Windows | ## Updating To update to the latest version: ```bash theme={null} npm update -g @castari/cli ``` ## Troubleshooting If you see `EACCES` errors, either: 1. Use a Node version manager like [nvm](https://github.com/nvm-sh/nvm) (recommended) 2. Or fix npm permissions: [npm docs](https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally) Make sure your global npm bin directory is in your PATH: ```bash theme={null} npm bin -g ``` Add the output directory to your shell's PATH. Update Node.js to version 18 or higher. We recommend using [nvm](https://github.com/nvm-sh/nvm): ```bash theme={null} nvm install 18 nvm use 18 ``` ## Next Steps Deploy your first agent in under 5 minutes # Quick Start Source: https://docs.castari.com/quickstart Deploy your first agent in under 5 minutes # Quick Start Deploy your first Claude agent in under 5 minutes. **Prerequisites:** Node.js 18+ and npm installed. **Using Claude Code?** Type `/castari-deploy` and the skill handles all of these steps for you. Install it with `npx skills add castari/cli`. [Learn more](/guides/claude-code). ```bash theme={null} npm install -g @castari/cli ``` Verify installation: ```bash theme={null} cast --version ``` ```bash theme={null} cast login ``` This opens your browser to authenticate. Once complete, you'll see: ``` ✓ Logged in as you@example.com ``` ```bash theme={null} cast init my-agent ``` Select the `default` template when prompted. This creates a coding agent with file and bash tools. ``` ? Select a template: ❯ default — Coding agent with file and bash tools (like Claude Code) research-agent — Deep research with web search and document synthesis support-agent — Customer support with ticket handling and escalation mcp-tools — Agent with example MCP server integration ✓ Created my-agent/ from default template ✓ Installed dependencies ``` ```bash theme={null} cd my-agent cast deploy ``` Wait for deployment to complete: ``` ⠋ Deploying my-agent... ✓ Agent 'my-agent' deployed! ``` ```bash theme={null} cast invoke my-agent "What files are in the current directory?" ``` Your agent responds: ``` The current directory contains: - src/index.ts - package.json - castari.json - CLAUDE.md - README.md ``` ## You did it! Your agent is deployed and running. Here's what you can do next: Edit the code and CLAUDE.md to change behavior Add API keys and environment variables Research agents, support agents, and more Invoke agents programmatically # Agents API Source: https://docs.castari.com/sdk/agents Manage agents programmatically # Agents API The Agents API lets you list, create, deploy, and invoke agents. Access via `client.agents`: ```typescript theme={null} const client = new CastariClient({ apiKey: '...' }); const agents = client.agents; ``` ## Methods ### list() List all agents for the authenticated user. ```typescript theme={null} const agents = await client.agents.list(); ``` **Returns:** `Promise` **Example:** ```typescript theme={null} const agents = await client.agents.list(); for (const agent of agents) { console.log(`${agent.name} (${agent.slug}) - ${agent.status}`); } ``` *** ### get(slug) Get a specific agent by slug. ```typescript theme={null} const agent = await client.agents.get(slug); ``` **Parameters:** | Name | Type | Description | | ------ | -------- | ----------------------- | | `slug` | `string` | The agent's unique slug | **Returns:** `Promise` **Example:** ```typescript theme={null} const agent = await client.agents.get('my-agent'); console.log(agent.status); // 'active' ``` **Errors:** * `404` — Agent not found *** ### create(options) Create a new agent. ```typescript theme={null} const agent = await client.agents.create(options); ``` **Parameters:** | Name | Type | Required | Description | | --------------------- | ------------------ | -------- | ------------------------------------------------------------ | | `options.name` | `string` | Yes | Display name for the agent | | `options.slug` | `string` | No | Unique identifier (auto-generated from name if not provided) | | `options.description` | `string` | No | Agent description | | `options.sourceType` | `'git' \| 'local'` | No | Source type (default: `'git'`) | | `options.gitRepoUrl` | `string` | No | Git repository URL (required when sourceType is `'git'`) | **Returns:** `Promise` **Example:** ```typescript theme={null} const agent = await client.agents.create({ name: 'My Agent', slug: 'my-agent', // optional gitRepoUrl: 'https://github.com/user/my-agent', }); ``` *** ### delete(slug) Delete an agent. ```typescript theme={null} await client.agents.delete(slug); ``` **Parameters:** | Name | Type | Description | | ------ | -------- | ---------------- | | `slug` | `string` | The agent's slug | **Returns:** `Promise` **Example:** ```typescript theme={null} await client.agents.delete('my-agent'); ``` This permanently deletes the agent, its secrets, and all invocation history. *** ### deploy(slug) Deploy an agent. ```typescript theme={null} const agent = await client.agents.deploy(slug); ``` **Parameters:** | Name | Type | Description | | ------ | -------- | ---------------- | | `slug` | `string` | The agent's slug | **Returns:** `Promise` **Example:** ```typescript theme={null} const agent = await client.agents.deploy('my-agent'); console.log(agent.status); // 'deploying' → 'active' ``` Deployment is asynchronous. The returned agent will have status `deploying`. Poll `get()` to check when it becomes `active`. *** ### stop(slug) Stop a running agent. ```typescript theme={null} const agent = await client.agents.stop(slug); ``` **Parameters:** | Name | Type | Description | | ------ | -------- | ---------------- | | `slug` | `string` | The agent's slug | **Returns:** `Promise` **Example:** ```typescript theme={null} const agent = await client.agents.stop('my-agent'); console.log(agent.status); // 'stopped' ``` *** ### invoke(slug, options) Invoke an agent with a prompt. ```typescript theme={null} const result = await client.agents.invoke(slug, options); ``` **Parameters:** | Name | Type | Required | Description | | ------------------- | -------- | -------- | -------------------------------------- | | `slug` | `string` | Yes | The agent's slug | | `options.prompt` | `string` | Yes | The prompt to send | | `options.sessionId` | `string` | No | Session ID for conversation continuity | **Returns:** `Promise` **Example:** ```typescript theme={null} const result = await client.agents.invoke('my-agent', { prompt: 'What files are in the current directory?' }); console.log(result.response_content); console.log(`Cost: $${result.total_cost_usd}`); console.log(`Duration: ${result.duration_ms}ms`); ``` **With session (multi-turn conversation):** ```typescript theme={null} // First turn const result1 = await client.agents.invoke('my-agent', { prompt: 'Create a file called hello.txt', sessionId: 'my-session', }); // Second turn (same session, sandbox preserved) const result2 = await client.agents.invoke('my-agent', { prompt: 'What did you just create?', sessionId: 'my-session', }); ``` **Response:** ```typescript theme={null} { invocation_id: 'inv_abc123', session_id: 'my-session', response_content: 'The current directory contains...', input_tokens: 124, output_tokens: 1110, total_cost_usd: 0.02, duration_ms: 2341, status: 'completed' } ``` *** ### uploadCode(slug, file, filename, options?) Upload code directly to an agent and deploy. ```typescript theme={null} const result = await client.agents.uploadCode(slug, file, filename, options?); ``` **Parameters:** | Name | Type | Required | Description | | -------------------- | --------- | -------- | ------------------------------------------ | | `slug` | `string` | Yes | The agent's slug | | `file` | `Blob` | Yes | The code archive file | | `filename` | `string` | Yes | Filename (e.g., `'code.tar.gz'`) | | `options.autoDeploy` | `boolean` | No | Auto-deploy after upload (default: `true`) | **Returns:** `Promise` **Example:** ```typescript theme={null} const file = new Blob([tarGzBuffer], { type: 'application/gzip' }); const result = await client.agents.uploadCode('my-agent', file, 'code.tar.gz'); console.log(result.status); // 'active' ``` *** ### listSecrets(slug) List secret keys for an agent (values are never returned). ```typescript theme={null} const secrets = await client.agents.listSecrets(slug); ``` **Parameters:** | Name | Type | Description | | ------ | -------- | ---------------- | | `slug` | `string` | The agent's slug | **Returns:** `Promise` **Example:** ```typescript theme={null} const secrets = await client.agents.listSecrets('my-agent'); // [{ key: 'OPENAI_API_KEY' }, { key: 'DATABASE_URL' }] ``` *** ### setSecret(slug, key, value) Set a secret for an agent. ```typescript theme={null} await client.agents.setSecret(slug, key, value); ``` **Parameters:** | Name | Type | Description | | ------- | -------- | ---------------- | | `slug` | `string` | The agent's slug | | `key` | `string` | The secret key | | `value` | `string` | The secret value | **Returns:** `Promise` **Example:** ```typescript theme={null} await client.agents.setSecret('my-agent', 'OPENAI_API_KEY', 'sk-xxx'); ``` *** ### deleteSecret(slug, key) Delete a secret from an agent. ```typescript theme={null} await client.agents.deleteSecret(slug, key); ``` **Parameters:** | Name | Type | Description | | ------ | -------- | ------------------------ | | `slug` | `string` | The agent's slug | | `key` | `string` | The secret key to delete | **Returns:** `Promise` **Example:** ```typescript theme={null} await client.agents.deleteSecret('my-agent', 'OLD_API_KEY'); ``` *** ## Full Example ```typescript theme={null} import { CastariClient } from '@castari/sdk'; async function main() { const client = new CastariClient({ apiKey: process.env.CASTARI_API_KEY, }); // List all agents const agents = await client.agents.list(); console.log(`You have ${agents.length} agents`); // Get specific agent const agent = await client.agents.get('my-agent'); if (agent.status !== 'active') { // Deploy if not active await client.agents.deploy('my-agent'); } // Invoke const result = await client.agents.invoke('my-agent', { prompt: 'Write a haiku about coding', }); console.log(result.response_content); } main(); ``` ## See Also * [Secrets API](/sdk/secrets) — Manage secrets * [Types](/sdk/types) — TypeScript interfaces * [cast invoke](/cli/invoke) — CLI equivalent # Auth API Source: https://docs.castari.com/sdk/auth Authentication and API key management # Auth API The Auth API provides methods for user authentication and API key management. Access via `client.auth`: ```typescript theme={null} const client = new CastariClient({ apiKey: '...' }); const auth = client.auth; ``` ## Methods ### me() Get the current authenticated user's information. ```typescript theme={null} const user = await client.auth.me(); ``` **Returns:** `Promise` **Example:** ```typescript theme={null} const user = await client.auth.me(); console.log(user.email); // 'user@example.com' console.log(user.created_at); // '2025-01-15T10:00:00Z' ``` **Response type:** ```typescript theme={null} interface User { id: string; email: string; api_key_prefix?: string; created_at: string; } ``` *** ### listApiKeys() List all API keys for the authenticated user. ```typescript theme={null} const keys = await client.auth.listApiKeys(); ``` **Returns:** `Promise` **Example:** ```typescript theme={null} const keys = await client.auth.listApiKeys(); for (const key of keys) { console.log(`${key.name} (${key.prefix}...) - Created: ${key.created_at}`); } ``` **Response type:** ```typescript theme={null} interface ApiKeyInfo { id: string; name: string; prefix: string; created_at: string; last_used_at?: string; } ``` *** ### createApiKey(name?) Create a new named API key. ```typescript theme={null} const result = await client.auth.createApiKey(name?); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | --------------------------------------------------- | | `name` | `string` | No | Descriptive name for the key (default: `'Default'`) | **Returns:** `Promise` **Example:** ```typescript theme={null} const result = await client.auth.createApiKey('CI/CD Pipeline'); console.log(result.key); // 'cast_xxxxxxxx_xxxxxxxxxx' — save this! console.log(result.api_key.id); // key ID for future reference ``` The full API key (`result.key`) is only returned once at creation. Store it securely. **Response type:** ```typescript theme={null} interface ApiKeyCreateResponse { api_key: ApiKeyInfo; key: string; // Full API key — only shown once } ``` *** ### revokeApiKey(keyId?) Revoke an API key by its ID. ```typescript theme={null} await client.auth.revokeApiKey(keyId?); ``` **Parameters:** | Name | Type | Required | Description | | ------- | -------- | -------- | --------------------------- | | `keyId` | `string` | No | The ID of the key to revoke | **Returns:** `Promise` **Example:** ```typescript theme={null} await client.auth.revokeApiKey('ak_abc123'); ``` *** ## See Also * [cast apikey](/cli/apikey) — CLI equivalent * [CastariClient](/sdk/client) — Client setup * [Types](/sdk/types) — TypeScript interfaces # CastariClient Source: https://docs.castari.com/sdk/client SDK client configuration and setup # CastariClient The main client for interacting with the Castari API. ## Constructor ```typescript theme={null} import { CastariClient } from '@castari/sdk'; const client = new CastariClient(options); ``` ## Options ```typescript theme={null} interface CastariClientOptions { apiKey?: string; token?: string; baseUrl?: string; } ``` | Option | Type | Description | | --------- | -------- | ---------------------------------------------------------- | | `apiKey` | `string` | API key for authentication (recommended) | | `token` | `string` | OAuth/JWT token for user-scoped access | | `baseUrl` | `string` | Override API base URL (default: `https://api.castari.com`) | Provide either `apiKey` or `token`, not both. If neither is provided, the client will throw an error on the first request. ## Authentication Methods ### API Key Best for server-side applications, CI/CD, and automation: ```typescript theme={null} const client = new CastariClient({ apiKey: process.env.CASTARI_API_KEY, }); ``` API keys look like: `cast_xxxxxxxx_xxxxxxxxxx` Generate one in the [Castari Dashboard](https://app.castari.com). ### OAuth Token Best for user-facing applications where you want user-scoped access: ```typescript theme={null} const client = new CastariClient({ token: userJwtToken, }); ``` ## Properties | Property | Type | Description | | --------- | ---------------------------- | ------------------------------------- | | `agents` | [`AgentsAPI`](/sdk/agents) | Agent management methods | | `auth` | [`AuthAPI`](/sdk/auth) | Authentication and API key management | | `usage` | [`UsageAPI`](/sdk/usage) | Usage statistics and costs | | `storage` | [`StorageAPI`](/sdk/storage) | Cloud storage bucket management | | `mounts` | [`MountsAPI`](/sdk/mounts) | Agent mount configuration | | `files` | [`FilesAPI`](/sdk/files) | Managed file storage (v2) | ## Example Usage ```typescript theme={null} import { CastariClient } from '@castari/sdk'; // Create client const client = new CastariClient({ apiKey: process.env.CASTARI_API_KEY, }); // Use agents API const agents = await client.agents.list(); const agent = await client.agents.get('my-agent'); await client.agents.deploy('my-agent'); // Use secrets API const secrets = await client.secrets.list('my-agent'); await client.secrets.set('my-agent', 'API_KEY', 'value'); ``` ## Custom Base URL For self-hosted or development environments: ```typescript theme={null} const client = new CastariClient({ apiKey: process.env.CASTARI_API_KEY, baseUrl: 'https://api.my-castari-instance.com', }); ``` ## Environment Variables The SDK respects these environment variables: | Variable | Description | | ----------------- | ---------------------------------------------- | | `CASTARI_API_KEY` | Default API key if not provided in constructor | | `CASTARI_API_URL` | Default base URL if not provided | ```typescript theme={null} // Uses CASTARI_API_KEY from environment const client = new CastariClient({}); ``` ## See Also * [Agents API](/sdk/agents) — Manage agents * [Secrets API](/sdk/secrets) — Manage secrets * [Auth API](/sdk/auth) — Authentication and API keys * [Usage API](/sdk/usage) — Usage statistics * [Storage API](/sdk/storage) — Cloud storage buckets * [Mounts API](/sdk/mounts) — Agent mounts * [Files API](/sdk/files) — Managed file storage * [Types](/sdk/types) — TypeScript interfaces # Files API Source: https://docs.castari.com/sdk/files Managed file storage for agents # Files API The Files API provides managed file storage (Storage v2). Upload files to Castari's managed storage and attach them to agents. Access via `client.files`: ```typescript theme={null} const client = new CastariClient({ apiKey: '...' }); const files = client.files; ``` ## Methods ### upload(file, filename, options?) Upload a file to managed storage. ```typescript theme={null} const result = await client.files.upload(file, filename, options?); ``` **Parameters:** | Name | Type | Required | Description | | --------------------- | ---------- | -------- | --------------------- | | `file` | `Blob` | Yes | The file data | | `filename` | `string` | Yes | File name | | `options.description` | `string` | No | File description | | `options.tags` | `string[]` | No | Tags for organization | **Returns:** `Promise` **Example:** ```typescript theme={null} const file = new Blob(['Hello, world!'], { type: 'text/plain' }); const result = await client.files.upload(file, 'hello.txt', { description: 'Greeting file', tags: ['example'], }); console.log(result.file_id); ``` *** ### list(options?) List files in managed storage. ```typescript theme={null} const result = await client.files.list(options?); ``` **Parameters:** | Name | Type | Required | Description | | ---------------- | -------------------------------- | -------- | ------------------------- | | `options.limit` | `number` | No | Max results (default: 50) | | `options.offset` | `number` | No | Pagination offset | | `options.scope` | `'user' \| 'agent' \| 'session'` | No | Filter by scope | | `options.tags` | `string[]` | No | Filter by tags | | `options.search` | `string` | No | Search by filename | **Returns:** `Promise` *** ### get(fileId) Get file metadata. ```typescript theme={null} const file = await client.files.get(fileId); ``` **Returns:** `Promise` *** ### update(fileId, options) Update file metadata. ```typescript theme={null} const file = await client.files.update(fileId, options); ``` **Returns:** `Promise` *** ### delete(fileId) Delete a file from managed storage. ```typescript theme={null} await client.files.delete(fileId); ``` **Returns:** `Promise` *** ### download(fileId) Download a file. ```typescript theme={null} const response = await client.files.download(fileId); ``` **Returns:** `Promise` *** ### getUsage() Get storage usage statistics. ```typescript theme={null} const usage = await client.files.getUsage(); ``` **Returns:** `Promise` **Example:** ```typescript theme={null} const usage = await client.files.getUsage(); console.log(`${usage.total_files} files, ${usage.total_mb} MB used (${usage.usage_percent}%)`); ``` **Response type:** ```typescript theme={null} interface StorageUsage { total_files: number; total_bytes: number; total_mb: number; limit_mb: number; usage_percent: number; } ``` *** ### getUploadUrl(filename, sizeBytes, options?) Get a presigned upload URL for large files. ```typescript theme={null} const presigned = await client.files.getUploadUrl(filename, sizeBytes, options?); ``` **Returns:** `Promise` *** ### confirmUpload(fileId, sha256Hash) Confirm a presigned upload completed successfully. ```typescript theme={null} const file = await client.files.confirmUpload(fileId, sha256Hash); ``` **Returns:** `Promise` *** ### attachToAgent(agentSlug, options) Attach a file to an agent. ```typescript theme={null} const agentFile = await client.files.attachToAgent(agentSlug, options); ``` **Parameters:** | Name | Type | Required | Description | | ------------------- | --------- | -------- | ----------------------- | | `agentSlug` | `string` | Yes | The agent's slug | | `options.fileId` | `string` | Yes | File ID to attach | | `options.mountPath` | `string` | No | Path inside the sandbox | | `options.readOnly` | `boolean` | No | Mount as read-only | **Returns:** `Promise` *** ### listAgentFiles(agentSlug) List files attached to an agent. ```typescript theme={null} const result = await client.files.listAgentFiles(agentSlug); ``` **Returns:** `Promise` *** ### detachFromAgent(agentSlug, fileId) Detach a file from an agent. ```typescript theme={null} await client.files.detachFromAgent(agentSlug, fileId); ``` **Returns:** `Promise` *** ## See Also * [cast files](/cli/files) — CLI equivalent * [Storage API](/sdk/storage) — Cloud bucket storage * [Types](/sdk/types) — TypeScript interfaces # Mounts API Source: https://docs.castari.com/sdk/mounts Mount storage buckets to agent sandboxes # Mounts API The Mounts API lets you mount cloud storage buckets to agent sandboxes, giving agents read or write access to external files. Access via `client.mounts`: ```typescript theme={null} const client = new CastariClient({ apiKey: '...' }); const mounts = client.mounts; ``` ## Methods ### getMounts(agentSlug) List all mounts for an agent. ```typescript theme={null} const mounts = await client.mounts.getMounts(agentSlug); ``` **Parameters:** | Name | Type | Description | | ----------- | -------- | ---------------- | | `agentSlug` | `string` | The agent's slug | **Returns:** `Promise` **Example:** ```typescript theme={null} const mounts = await client.mounts.getMounts('my-agent'); for (const mount of mounts) { console.log(`${mount.mount_path} → ${mount.bucket.name} (${mount.enabled ? 'enabled' : 'disabled'})`); } ``` *** ### addMount(agentSlug, options) Add a storage bucket mount to an agent. ```typescript theme={null} const mount = await client.mounts.addMount(agentSlug, options); ``` **Parameters:** | Name | Type | Required | Description | | ------------------------- | ------------------ | -------- | --------------------------------------- | | `agentSlug` | `string` | Yes | The agent's slug | | `options.bucketSlug` | `string` | Yes | Bucket to mount | | `options.mountPath` | `string` | Yes | Path inside the sandbox (e.g., `/data`) | | `options.sourcePrefix` | `string` | No | Bucket prefix to mount | | `options.permissionRules` | `PermissionRule[]` | No | Permission rules | | `options.cacheEnabled` | `boolean` | No | Enable caching | | `options.cacheTtlSeconds` | `number` | No | Cache TTL in seconds | **Returns:** `Promise` **Example:** ```typescript theme={null} const mount = await client.mounts.addMount('my-agent', { bucketSlug: 'production-data', mountPath: '/data', permissionRules: [{ path: '/', mode: 'ro' }], }); ``` *** ### updateMount(agentSlug, mountId, options) Update an existing mount. ```typescript theme={null} const mount = await client.mounts.updateMount(agentSlug, mountId, options); ``` **Parameters:** | Name | Type | Required | Description | | ------------------------- | ------------------ | -------- | ------------------------ | | `agentSlug` | `string` | Yes | The agent's slug | | `mountId` | `string` | Yes | The mount ID | | `options.mountPath` | `string` | No | New mount path | | `options.sourcePrefix` | `string` | No | New source prefix | | `options.permissionRules` | `PermissionRule[]` | No | New permission rules | | `options.cacheEnabled` | `boolean` | No | Enable/disable caching | | `options.cacheTtlSeconds` | `number` | No | New cache TTL | | `options.enabled` | `boolean` | No | Enable/disable the mount | **Returns:** `Promise` *** ### removeMount(agentSlug, mountId) Remove a mount from an agent. ```typescript theme={null} await client.mounts.removeMount(agentSlug, mountId); ``` **Parameters:** | Name | Type | Description | | ----------- | -------- | ---------------- | | `agentSlug` | `string` | The agent's slug | | `mountId` | `string` | The mount ID | **Returns:** `Promise` *** ## See Also * [cast mounts](/cli/mounts) — CLI equivalent * [Storage API](/sdk/storage) — Manage buckets * [Types](/sdk/types) — TypeScript interfaces # SDK Overview Source: https://docs.castari.com/sdk/overview Use Castari programmatically with TypeScript # SDK Overview The `@castari/sdk` package lets you manage agents programmatically. ## Installation ```bash theme={null} npm install @castari/sdk ``` ## Quick Example ```typescript theme={null} import { CastariClient } from '@castari/sdk'; const client = new CastariClient({ apiKey: process.env.CASTARI_API_KEY, }); // List agents const agents = await client.agents.list(); console.log(agents); // Deploy an agent await client.agents.deploy('my-agent'); // Invoke an agent const result = await client.agents.invoke('my-agent', { prompt: 'Hello!' }); console.log(result.response_content); ``` ## When to Use the SDK | Use Case | CLI or SDK? | | -------------------------------- | ----------- | | Manual deploys | CLI | | CI/CD pipelines | SDK | | Building apps that manage agents | SDK | | Quick testing | CLI | | Programmatic invocations | SDK | ## Authentication The SDK supports two authentication methods: ### API Key (Recommended for servers) ```typescript theme={null} const client = new CastariClient({ apiKey: 'cast_xxxxxxxx_xxxxxxxxxx', }); ``` Generate an API key in the [Castari Dashboard](https://app.castari.com). ### OAuth Token (For user-scoped access) ```typescript theme={null} const client = new CastariClient({ token: 'eyJhbGciOiJSUzI1NiIs...', // Clerk JWT }); ``` ## TypeScript Support The SDK is written in TypeScript and exports all types: ```typescript theme={null} import { CastariClient, Agent, AgentStatus, InvocationResponse, } from '@castari/sdk'; ``` ## Error Handling ```typescript theme={null} import { CastariClient, CastariError } from '@castari/sdk'; try { await client.agents.deploy('my-agent'); } catch (error) { if (error instanceof CastariError) { console.error(`API Error: ${error.message}`); console.error(`Status: ${error.status}`); } } ``` ## Next Steps Client configuration and setup List, deploy, and invoke agents Manage agent secrets TypeScript interfaces # Secrets API Source: https://docs.castari.com/sdk/secrets Manage agent secrets programmatically # Secrets API The Secrets API lets you manage environment variables for your agents. Access via `client.secrets`: ```typescript theme={null} const client = new CastariClient({ apiKey: '...' }); const secrets = client.secrets; ``` ## Methods ### list(slug) List all secrets for an agent. ```typescript theme={null} const secrets = await client.secrets.list(slug); ``` **Parameters:** | Name | Type | Description | | ------ | -------- | ---------------- | | `slug` | `string` | The agent's slug | **Returns:** `Promise` **Example:** ```typescript theme={null} const secrets = await client.secrets.list('my-agent'); for (const secret of secrets) { console.log(`${secret.key} - created ${secret.created_at}`); } ``` Secret values are never returned by the API. Only keys and metadata are included. *** ### set(slug, key, value) Set a secret for an agent. ```typescript theme={null} await client.secrets.set(slug, key, value); ``` **Parameters:** | Name | Type | Description | | ------- | -------- | ------------------------------------ | | `slug` | `string` | The agent's slug | | `key` | `string` | Secret name (e.g., `OPENAI_API_KEY`) | | `value` | `string` | Secret value | **Returns:** `Promise` **Example:** ```typescript theme={null} await client.secrets.set( 'my-agent', 'OPENAI_API_KEY', 'sk-abc123...' ); ``` Setting a secret with an existing key will overwrite the previous value. *** ### delete(slug, key) Delete a secret from an agent. ```typescript theme={null} await client.secrets.delete(slug, key); ``` **Parameters:** | Name | Type | Description | | ------ | -------- | -------------------- | | `slug` | `string` | The agent's slug | | `key` | `string` | Secret key to delete | **Returns:** `Promise` **Example:** ```typescript theme={null} await client.secrets.delete('my-agent', 'OLD_API_KEY'); ``` ## Full Example ```typescript theme={null} import { CastariClient } from '@castari/sdk'; async function setupAgentSecrets() { const client = new CastariClient({ apiKey: process.env.CASTARI_API_KEY, }); const agentSlug = 'my-agent'; // Set multiple secrets await client.secrets.set(agentSlug, 'OPENAI_API_KEY', process.env.OPENAI_API_KEY); await client.secrets.set(agentSlug, 'DATABASE_URL', process.env.DATABASE_URL); // List to verify const secrets = await client.secrets.list(agentSlug); console.log(`Agent has ${secrets.length} secrets configured`); // Clean up old secret await client.secrets.delete(agentSlug, 'DEPRECATED_KEY'); } setupAgentSecrets(); ``` ## CI/CD Example Setting secrets in a GitHub Actions workflow: ```yaml theme={null} - name: Configure agent secrets env: CASTARI_API_KEY: ${{ secrets.CASTARI_API_KEY }} OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} run: | npx ts-node scripts/setup-secrets.ts ``` ```typescript theme={null} // scripts/setup-secrets.ts import { CastariClient } from '@castari/sdk'; const client = new CastariClient({ apiKey: process.env.CASTARI_API_KEY, }); await client.secrets.set('my-agent', 'OPENAI_API_KEY', process.env.OPENAI_API_KEY); ``` ## See Also * [Agents API](/sdk/agents) — Manage agents * [cast secrets](/cli/secrets) — CLI equivalent * [Secrets Concept](/concepts/secrets) — How secrets work # Storage API Source: https://docs.castari.com/sdk/storage Manage cloud storage buckets # Storage API The Storage API lets you manage cloud storage buckets (S3, GCS, R2) that can be mounted to agent sandboxes. Access via `client.storage`: ```typescript theme={null} const client = new CastariClient({ apiKey: '...' }); const storage = client.storage; ``` ## Methods ### getBuckets() List all storage buckets. ```typescript theme={null} const buckets = await client.storage.getBuckets(); ``` **Returns:** `Promise` *** ### createBucket(options) Create a new storage bucket configuration. ```typescript theme={null} const bucket = await client.storage.createBucket(options); ``` **Parameters:** | Name | Type | Required | Description | | --------------------- | ----------------------- | -------- | ------------------------------------- | | `options.name` | `string` | Yes | Display name | | `options.slug` | `string` | Yes | URL-safe identifier | | `options.provider` | `'s3' \| 'gcs' \| 'r2'` | Yes | Cloud storage provider | | `options.bucketName` | `string` | Yes | Actual bucket name in the provider | | `options.region` | `string` | No | AWS region (for S3) | | `options.endpointUrl` | `string` | No | Custom endpoint URL (required for R2) | **Returns:** `Promise` **Example:** ```typescript theme={null} const bucket = await client.storage.createBucket({ name: 'Production Data', slug: 'production-data', provider: 's3', bucketName: 'my-data-bucket', region: 'us-east-1', }); ``` *** ### getBucket(slug) Get a specific bucket by slug. ```typescript theme={null} const bucket = await client.storage.getBucket(slug); ``` **Parameters:** | Name | Type | Description | | ------ | -------- | ----------------- | | `slug` | `string` | The bucket's slug | **Returns:** `Promise` *** ### updateBucket(slug, options) Update a bucket configuration. ```typescript theme={null} const bucket = await client.storage.updateBucket(slug, options); ``` **Parameters:** | Name | Type | Required | Description | | --------------------- | -------- | -------- | ----------------- | | `slug` | `string` | Yes | The bucket's slug | | `options.name` | `string` | No | New display name | | `options.bucketName` | `string` | No | New bucket name | | `options.region` | `string` | No | New region | | `options.endpointUrl` | `string` | No | New endpoint URL | **Returns:** `Promise` *** ### deleteBucket(slug) Delete a bucket configuration. ```typescript theme={null} await client.storage.deleteBucket(slug); ``` **Returns:** `Promise` *** ### setCredentials(slug, credentials) Set credentials for a bucket. ```typescript theme={null} await client.storage.setCredentials(slug, credentials); ``` **Parameters:** | Name | Type | Required | Description | | -------------------------------- | -------- | -------- | ------------------------ | | `slug` | `string` | Yes | The bucket's slug | | `credentials.accessKeyId` | `string` | No | AWS/R2 access key ID | | `credentials.secretAccessKey` | `string` | No | AWS/R2 secret access key | | `credentials.serviceAccountJson` | `string` | No | GCS service account JSON | **Returns:** `Promise` *** ### testConnection(slug) Test the connection to a bucket. ```typescript theme={null} const result = await client.storage.testConnection(slug); ``` **Returns:** `Promise` *** ### listFiles(slug, prefix?) List files in a bucket. ```typescript theme={null} const files = await client.storage.listFiles(slug, prefix?); ``` **Parameters:** | Name | Type | Required | Description | | -------- | -------- | -------- | ---------------------- | | `slug` | `string` | Yes | The bucket's slug | | `prefix` | `string` | No | Filter files by prefix | **Returns:** `Promise` *** ### getDownloadUrl(slug, path, options?) Get a presigned download URL for a file. ```typescript theme={null} const presigned = await client.storage.getDownloadUrl(slug, path, options?); ``` **Returns:** `Promise` *** ### getUploadUrl(slug, path, options?) Get a presigned upload URL for a file. ```typescript theme={null} const presigned = await client.storage.getUploadUrl(slug, path, options?); ``` **Returns:** `Promise` *** ## See Also * [cast buckets](/cli/buckets) — CLI equivalent * [Mounts API](/sdk/mounts) — Mount buckets to agents * [Types](/sdk/types) — TypeScript interfaces # Types Source: https://docs.castari.com/sdk/types TypeScript interfaces and types # Types All TypeScript types exported by `@castari/sdk`. ## Agent Represents a Castari agent. ```typescript theme={null} interface Agent { id: string; user_id: string; name: string; slug: string; description?: string | null; source_type: AgentSourceType; git_repo_url?: string | null; git_branch: string; source_hash?: string | null; default_model: string; max_turns: number; timeout_seconds: number; status: AgentStatus; status_message?: string | null; sandbox_id?: string | null; created_at: string; updated_at: string; } ``` | Field | Type | Description | | -------------- | ----------------- | --------------------------------- | | `id` | `string` | Unique identifier | | `name` | `string` | Display name | | `slug` | `string` | URL-safe identifier | | `status` | `AgentStatus` | Current status | | `source_type` | `AgentSourceType` | `'git'` or `'local'` | | `git_repo_url` | `string?` | Source repository URL | | `sandbox_id` | `string?` | Active sandbox ID (when deployed) | | `created_at` | `string` | ISO 8601 timestamp | | `updated_at` | `string` | ISO 8601 timestamp | *** ## AgentStatus Possible agent statuses. ```typescript theme={null} type AgentStatus = | 'draft' | 'deploying' | 'active' | 'stopped' | 'error'; ``` | Status | Description | | ----------- | --------------------------------- | | `draft` | Created but not yet deployed | | `deploying` | Deployment in progress | | `active` | Running and ready for invocations | | `stopped` | Manually stopped | | `error` | Deployment or runtime error | *** ## AgentSourceType Source type for agent code. ```typescript theme={null} type AgentSourceType = 'git' | 'local'; ``` *** ## InvocationResponse Response from invoking an agent. ```typescript theme={null} interface InvocationResponse { invocation_id: string; session_id: string; sandbox_id?: string | null; response_content: string; input_tokens: number; output_tokens: number; total_cost_usd: number | string; duration_ms: number; status: 'completed' | 'failed'; } ``` | Field | Type | Description | | ------------------ | ------------------ | -------------------------------------- | | `invocation_id` | `string` | Unique identifier (e.g., `inv_abc123`) | | `session_id` | `string` | Session ID for the invocation | | `response_content` | `string` | Agent's response text | | `input_tokens` | `number` | Tokens in the prompt | | `output_tokens` | `number` | Tokens in the response | | `total_cost_usd` | `number \| string` | Total cost in USD | | `duration_ms` | `number` | Execution time in milliseconds | | `status` | `string` | `'completed'` or `'failed'` | *** ## InvokeOptions Options for invoking an agent. ```typescript theme={null} interface InvokeOptions { prompt: string; sessionId?: string; } ``` | Field | Type | Required | Description | | ----------- | -------- | -------- | -------------------------------------- | | `prompt` | `string` | Yes | The prompt to send | | `sessionId` | `string` | No | Session ID for conversation continuity | *** ## CreateAgentOptions Options for creating an agent. ```typescript theme={null} interface CreateAgentOptions { name: string; slug?: string; description?: string; sourceType?: AgentSourceType; gitRepoUrl?: string; } ``` | Field | Type | Required | Description | | ------------- | ----------------- | -------- | ----------------------------------------------- | | `name` | `string` | Yes | Display name for the agent | | `slug` | `string` | No | URL-safe identifier (auto-generated if omitted) | | `description` | `string` | No | Agent description | | `sourceType` | `AgentSourceType` | No | `'git'` (default) or `'local'` | | `gitRepoUrl` | `string` | No | Git repository URL | *** ## UploadResponse Response from uploading code. ```typescript theme={null} interface UploadResponse { agent_id: string; source_hash: string; status: AgentStatus; sandbox_id?: string | null; message: string; } ``` *** ## Secret Represents a secret (metadata only — values are never returned). ```typescript theme={null} interface Secret { key: string; } ``` | Field | Type | Description | | ----- | -------- | ------------------------------------ | | `key` | `string` | Secret name (e.g., `OPENAI_API_KEY`) | *** ## CastariClientOptions Options for creating a client. ```typescript theme={null} interface CastariClientOptions { apiKey?: string; token?: string; baseUrl?: string; } ``` | Field | Type | Description | | --------- | -------- | ------------------------------------------------- | | `apiKey` | `string` | API key (starts with `cast_`) | | `token` | `string` | OAuth token | | `baseUrl` | `string` | API base URL (default: `https://api.castari.com`) | *** ## CastariError Error thrown by SDK operations. ```typescript theme={null} class CastariError extends Error { statusCode: number; code?: string; } ``` | Field | Type | Description | | ------------ | --------- | ------------------------------------ | | `message` | `string` | Human-readable error message | | `statusCode` | `number` | HTTP status code | | `code` | `string?` | Error code (e.g., `agent_not_found`) | **Example:** ```typescript theme={null} try { await client.agents.get('nonexistent'); } catch (error) { if (error instanceof CastariError) { console.log(error.statusCode); // 404 console.log(error.message); // "Agent not found" } } ``` *** ## Storage v2 Types The SDK includes types for managed file storage (Storage v2): * `ManagedFile` — File metadata (id, filename, size, scope, tags, status) * `FileUploadResponse` — Upload result * `ManagedFileList` — Paginated file list with metadata * `StorageUsage` — Quota information (total files, bytes, limits) * `PresignedUpload` — Presigned URL for large file uploads * `AgentFile` — File attached to an agent * `AgentFileList` — List of agent-attached files See the full type definitions in [types.ts](https://github.com/castari/cli/blob/main/packages/sdk/src/types.ts). *** ## Importing Types All types are exported from the main package: ```typescript theme={null} import { CastariClient, CastariClientOptions, CastariError, Agent, AgentStatus, AgentSourceType, InvocationResponse, InvokeOptions, CreateAgentOptions, UpdateAgentOptions, UploadResponse, Secret, User, ApiKeyInfo, ApiKeyCreateResponse, UsageSummary, DailyUsage, Bucket, Mount, ManagedFile, StorageUsage, } from '@castari/sdk'; ``` ## See Also * [CastariClient](/sdk/client) — Client setup * [Agents API](/sdk/agents) — Agent methods * [Secrets API](/sdk/secrets) — Secrets methods * [Auth API](/sdk/auth) — Authentication methods * [Usage API](/sdk/usage) — Usage statistics * [Storage API](/sdk/storage) — Cloud bucket storage * [Mounts API](/sdk/mounts) — Agent mounts * [Files API](/sdk/files) — Managed file storage # Usage API Source: https://docs.castari.com/sdk/usage Query usage statistics and costs # Usage API The Usage API lets you query invocation counts, token usage, and costs. Access via `client.usage`: ```typescript theme={null} const client = new CastariClient({ apiKey: '...' }); const usage = client.usage; ``` ## Methods ### summary(options?) Get a usage summary for a time period. ```typescript theme={null} const summary = await client.usage.summary(options?); ``` **Parameters:** | Name | Type | Required | Description | | -------------- | -------- | -------- | ----------------------------------------- | | `options.days` | `number` | No | Number of days to include (default: `30`) | **Returns:** `Promise` **Example:** ```typescript theme={null} const summary = await client.usage.summary({ days: 7 }); console.log(`Invocations: ${summary.total_invocations}`); console.log(`Input tokens: ${summary.total_input_tokens}`); console.log(`Output tokens: ${summary.total_output_tokens}`); console.log(`Total cost: $${summary.total_cost_usd}`); ``` **Response type:** ```typescript theme={null} interface UsageSummary { total_invocations: number; total_input_tokens: number; total_output_tokens: number; total_cost_usd: number; period_start: string; period_end: string; } ``` *** ### daily(options?) Get a daily usage breakdown. ```typescript theme={null} const days = await client.usage.daily(options?); ``` **Parameters:** | Name | Type | Required | Description | | -------------- | -------- | -------- | ----------------------------------------- | | `options.days` | `number` | No | Number of days to include (default: `30`) | **Returns:** `Promise` **Example:** ```typescript theme={null} const days = await client.usage.daily({ days: 7 }); for (const day of days) { console.log(`${day.date}: ${day.invocation_count} invocations, $${day.cost_usd}`); } ``` **Response type:** ```typescript theme={null} interface DailyUsage { date: string; invocation_count: number; input_tokens: number; output_tokens: number; cost_usd: number; } ``` *** ## See Also * [cast usage](/cli/usage) — CLI equivalent * [Types](/sdk/types) — TypeScript interfaces