# Concepts

AgentSky is built around four primitives: **agents**, **sessions**, **events**, and **universes**. Understanding these makes every API response predictable.

## Agents

An **agent** is a reusable specification — not a running process. It stores:

- The **harness** (Claude Code, Codex, Hermes, or a custom harness): determines what model orchestration the agent can do.
- **Instructions**: the system prompt and personality.
- **Capabilities**: which built-in tools the agent may call (web search, code execution, browser automation, …).
- **Skills**: versioned instruction bundles loaded on demand.
- **agent.toml**: the declarative file that configures all of the above and is committed to your repo.

Creating an agent does not start it running. You interact with it through sessions.

```
Agent
├── id: agent_…
├── harness: hermes
├── displayName: Research Agent
├── defaultSessionId: sess_…   ← created automatically on first launch
└── capabilities: [exa.search]
```

## Sessions

A **session** is one running conversation with an agent. It holds:

- The **event log**: every message, response, tool call, and status change, in order.
- The **context window**: the live slice of the event log the agent sees on its next turn.
- The **status**: `idle`, `running`, `error`, `terminated`.

A session is the unit you stream, continue, and replay. Every agent gets a `defaultSessionId` at launch — good for one-off use. For multi-user applications, create a session per user conversation.

Sessions live forever (until you delete them). An idle session can be continued days later; it picks up context from the event log.

```
Session
├── id: sess_…
├── agent: agent_…
├── status: idle
├── llm: claude-sonnet-5
└── events: […]
```

## Events

Events are the messages-in and messages-out of a session. The session's event log is append-only.

**Events you send:**

| Type | When to use |
|---|---|
| `user.message` | A new message from a user or your application |
| `user.interrupt` | Stop the agent mid-turn cleanly |
| `system.message` | Inject a system-level message (hidden from user but visible to agent) |

**Events the agent produces:**

| Type | What it carries |
|---|---|
| `agent.message` | A completed text response |
| `agent.message.delta` | A streaming chunk of a text response |
| `agent.tool_call` | An outbound tool invocation |
| `agent.tool_result` | The result of a tool call |
| `session.status_idle` | The agent finished its turn (includes `stop_reason`) |
| `session.error` | An unrecoverable error (includes code and message) |

The **stream** (`GET /v1/sessions/{id}/stream`) delivers events as Server-Sent Events in real time. The **event log** (`GET /v1/sessions/{id}/events`) returns the same objects in order after the fact. Both use the same `id` field — deduplicate by event id when replaying a partial stream.

### The session loop

Every turn follows the same shape:

```
POST /sessions/{id}/events   →  202 (queued)
GET  /sessions/{id}/stream   →  SSE: agent.message.delta … session.status_idle
POST /sessions/{id}/events   →  next turn
```

The stream is standing — open it once and it delivers every future turn. `session.status_idle` marks the end of a turn; `stop_reason` says why the agent stopped (`end_turn`, `tool_use`, `budget_reached`, `interrupted`, `error`).

## Universes (workspaces)

A **universe** is an isolated workspace — its own agents, sessions, members, billing, and API keys. Use one per customer tenant, per deployment environment, or per team.

```bash
# Create
curl -X POST https://api.agentsky.dev/v1/universes \
  -H "Authorization: Bearer ast_..." \
  -d '{ "slug": "acme", "name": "Acme" }'

# Act inside it
curl ... -H "X-Universe: acme"
```

Resources (agents, sessions, files) belong to exactly one universe. Members of that universe can see its resources. See [Authentication](https://agentsky.dev/docs/authentication.md) for how personal vs. scoped tokens interact with universes.

## Billing

AgentSky bills at three levels:

**Token usage:** every LLM call records input and output tokens. The model rate card is at `GET /v1/generation?id=…` and in the billing dashboard.

**Capabilities:** built-in tool calls (web search, browser automation) are charged per invocation at rates listed in the [Capabilities reference](https://agentsky.dev/docs/capabilities.md).

**Sessions:** session compute (hosting the pod between turns) is charged per active session-hour.

A **spend policy** lets you cap a session's total spend before it was created or at any time:

```bash
curl -X POST https://api.agentsky.dev/v1/sessions/sess_.../policies \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Spend cap",
    "kind": "SPEND_CAP",
    "config": { "hardCapUsdMicros": 5000000, "warnUsdMicros": 4000000 }
  }'
```

When the hard cap is hit, the session stops with `stop_reason.type: "budget_reached"`. Cumulative spend is on `GET /v1/sessions/{id}`.

## See also

- [Choose your path](https://agentsky.dev/docs/overview.md) — which integration to use for your situation
- [Authentication](https://agentsky.dev/docs/authentication.md) — tokens, scopes, X-Universe
- [Agent API guide](https://agentsky.dev/docs/agent-api.md) — end-to-end usage with code samples
- [API reference](https://agentsky.dev/docs/api.md) — full schema for every resource
