# Scout Live — Agent Skill

Welcome, agent. This document explains how to build and deploy applications on Scout Live.

## Quick Start

```bash
# 1. Get your API key from the dashboard
API_KEY="sk-live-xxx"

# 2. Create a tarball with your Dockerfile
tar -czf app.tar.gz Dockerfile package.json src/

# 3. Deploy
curl -X POST "https://scoutos.live/api/build?subdomain=my-app" \
  -H "Authorization: Bearer $API_KEY" \
  --data-binary @app.tar.gz

# 4. Your app is live at: https://my-app.scoutos.live
```

## Platform Overview

Scout Live is a deployment platform built for AI agents. Key concepts:

| Concept | What it means |
|---------|---------------|
| **App** | A containerized application with its own subdomain |
| **Subdomain** | `your-app.scoutos.live` — your app's public URL |
| **Build** | Kaniko builds your Dockerfile in-cluster |
| **Deploy** | Spawns a container with your image, assigns URL |
| **Ports** | Standard service interfaces (data, cache, queue, search, blob) |
| **Adapters** | Pre-provisioned shared services you can bind to |

## Ports and Adapters

**Ports** are standard interfaces that give your app access to external services. Instead of managing API keys, connection strings, and SDKs, your app simply calls a local URL.

### Available Ports

| Port | URL Pattern | What it provides |
|------|--------------|-------------------|
| **Data** | `http://localhost:${SCOUT_PORTS_URL}/data/...` | MongoDB-compatible document storage |
| **Cache** | `http://localhost:${SCOUT_PORTS_URL}/cache/...` | Redis-compatible key-value cache |
| **Search** | `http://localhost:${SCOUT_PORTS_URL}/search/...` | OpenSearch full-text search |
| **Queue** | `http://localhost:${SCOUT_PORTS_URL}/queue/...` | Kafka message queue |
| **Blob** | `http://localhost:${SCOUT_PORTS_URL}/blob/...` | S3-compatible object storage |
| **Agents** | `http://localhost:${SCOUT_PORTS_URL}/agents/...` | ScoutOS Agents API |

### How to Use Ports

Your app receives `SCOUT_PORTS_URL` as an environment variable. Call it like this:

```javascript
// Node.js / Bun
const PORTS_URL = process.env.SCOUT_PORTS_URL; // e.g. "http://localhost:3002"

// Store a document
await fetch(`${PORTS_URL}/data/todos`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ text: 'Build something awesome', completed: false })
});

// Query documents
const response = await fetch(`${PORTS_URL}/data/todos/find`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ filter: { completed: false } })
});
const { documents } = await response.json();
```

### Shared Adapters

Shared adapters are pre-provisioned services you can bind to your app. Available adapters:

| Adapter ID | Type | Description |
|------------|------|-------------|
| `shared-mongodb` | data | MongoDB document storage |
| `shared-valkey` | cache | Valkey (Redis-compatible) cache |
| `shared-search` | search | OpenSearch full-text search |
| `shared-kafka` | queue | Kafka message queue |
| `shared-spaces` | blob | DigitalOcean Spaces object storage |

To bind an adapter to your app:

```bash
curl -X POST "https://scoutos.live/api/apps/my-app/adapters/shared-mongodb" \
  -H "Authorization: Bearer $API_KEY"
```

Your app can then access it through the ports interface.

## Environment Variables

Your Dockerfile and app receive these environment variables automatically:

| Variable | Description |
|----------|-------------|
| `PORT` | The port your app should listen on (default: 3000) |
| `SCOUT_PORTS_URL` | Base URL for ports interface (e.g. `http://localhost:3002`) |
| `APP_SLUG` | Your app's subdomain (e.g. `my-app`) |
| `SCOUT_APP_URL` | Your app's public URL (e.g. `https://my-app.scoutos.live`) |

To define custom environment variables:

```bash
curl -X POST "https://scoutos.live/api/apps/my-app/env" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"key": "MY_SECRET", "value": "secret123", "secret": true}'
```

Secrets are encrypted and never exposed in the API.

## Building Your App

### Dockerfile Requirements

1. **Expose a port**: Your Dockerfile must `EXPOSE` the port your app listens on
2. **Use `PORT` env var**: Listen on `process.env.PORT || 3000`
3. **Single-stage or multi-stage**: Both work, Kaniko handles layer caching

**Example Dockerfile:**

```dockerfile
FROM oven/bun:1.3-slim

WORKDIR /app

COPY package.json bun.lock ./
RUN bun install --frozen-lockfile --production

COPY src ./src

ENV NODE_ENV=production
ENV PORT=3000

EXPOSE 3000

USER bun

CMD ["bun", "run", "src/index.ts"]
```

### Supported Runtimes

Any runtime that can run in a container:

- **Node.js / Bun** — Recommended for fastest cold starts
- **Python** — Flask, FastAPI, Django, etc.
- **Go** — Compile to a static binary
- **Rust** — Compile to a static binary
- **Ruby**, **Java**, **.NET** — All work

### Creating the Build Context

```bash
# Include all files needed to build
tar -czf app.tar.gz \
  Dockerfile \
  package.json \
  bun.lock \
  src/
```

## Deployment API

### Build and Deploy

```bash
POST /api/build?subdomain=my-app
Authorization: Bearer $API_KEY
Content-Type: application/x-tar

<tar.gz binary>
```

Response:
```json
{
  "buildId": "abc123",
  "status": "queued",
  "statusUrl": "/api/build/abc123/status",
  "logsUrl": "/api/build/abc123/logs",
  "url": "https://my-app.scoutos.live"
}
```

### Check Build Status

```bash
GET /api/build/{buildId}/status
Authorization: Bearer $API_KEY
```

Response:
```json
{
  "buildId": "abc123",
  "status": "completed",
  "url": "https://my-app.scoutos.live"
}
```

### Check App Health

```bash
GET /api/apps/{subdomain}/health
Authorization: Bearer $API_KEY
```

### View App Logs

```bash
GET /api/apps/{subdomain}/logs
Authorization: Bearer $API_KEY
```

### Delete App

```bash
DELETE /api/apps/{subdomain}
Authorization: Bearer $API_KEY
```

## Templates

Start from a pre-built template:

```bash
GET /api/templates              # List all templates
GET /api/templates/{id}         # Get template details

POST /api/apps/from-template   # Create app from template
Authorization: Bearer $API_KEY
Content-Type: application/json

{
  "templateId": "todo-app",
  "slug": "my-todos",
  "env": {
    "TODO_COLLECTION": "my-tasks"
  }
}
```

## ScoutOS Integration

Scout Live is part of the ScoutOS platform. You can use ScoutOS Agents in your app:

### Get a ScoutOS API Key

1. Sign up at https://scoutos.com
2. Create a workspace
3. Generate an API key
4. Add it to your app:

```bash
curl -X POST "https://scoutos.live/api/apps/my-app/env" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"key": "SCOUT_API_KEY", "value": "secret_xxx", "secret": true}'
```

### Use Agents in Your App

```javascript
const response = await fetch(`${process.env.SCOUT_PORTS_URL}/agents/{agent_id}/_interact`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    messages: [{ role: 'user', content: 'Hello!' }]
  })
});

const reader = response.body.getReader();
// Streaming response...
```

## Best Practices

### 1. Use Shared Adapters

Don't provision your own database. Bind to shared adapters:

```bash
# Bind MongoDB
curl -X POST https://scoutos.live/api/apps/my-app/adapters/shared-mongodb

# Now your app can use the data port
```

### 2. Listen on PORT

Always use the `PORT` environment variable:

```javascript
const port = process.env.PORT || 3000;
Bun.serve({ port, fetch: app.fetch });
```

### 3. Handle Graceful Shutdown

```javascript
process.on('SIGTERM', async () => {
  await closeConnections();
  process.exit(0);
});
```

### 4. Keep Builds Small

- Use `.dockerignore` to exclude unnecessary files
- Use multi-stage builds for compiled languages
- Install only production dependencies

### 5. Health Checks

Your app should respond to `/health` or `/api/health`:

```javascript
app.get('/health', (c) => c.json({ ok: true }));
```

## Limits and Quotas

| Resource | Free Tier | Pro |
|----------|-----------|-----|
| Apps | 10 | Unlimited |
| Builds/day | 50 | 500 |
| Storage/ app | 1 GiB | 10 GiB |
| Requests/month | 100k | Unlimited |

## Error Codes

| Code | Meaning |
|------|---------|
| 400 | Invalid request (check `error` field) |
| 401 | Missing or invalid API key |
| 403 | Permission denied (wrong scope) |
| 404 | App or resource not found |
| 409 | Subdomain already taken |
| 429 | Rate limited (retry after `Retry-After` header) |
| 500 | Server error (check build logs) |

## Getting Help

- **Documentation**: https://scoutos.live/docs
- **API Reference**: https://scoutos.live/openapi.json
- **GitHub**: https://github.com/scoutos-labs/scout-live
- **Discord**: https://discord.gg/clawd

## Summary

1. **Get an API key** from the dashboard
2. **Create a Dockerfile** that exposes `PORT`
3. **Package your app** as `tar.gz`
4. **POST to `/api/build`** with your subdomain
5. **Your app is live** at `https://your-app.scoutos.live`

For AI agents: This platform is designed for you. Use ports and adapters instead of managing infrastructure. Bind to shared services. Deploy with a single API call.