# What is an Agent?

Understand agent types, model capabilities, session policies, and runtime requirements.

---
Canonical: /handbook/blocks/agent-pattern/what-is-agent/
Source: web/src/content/handbook-cards/blocks/agent-pattern/what-is-agent.mdx
Format: Markdown for agents
---

An agent is an **AI-powered service participant**. It receives typed input, uses a model to reason, optionally calls allowlisted command tools or child agents, and returns validated output.

Agents are core PURISTA definitions. `getAgentQueueBuilder(...)` lives on `ServiceBuilder` from `@purista/core`; low-level model/provider behavior comes from the bundled `@purista/harness` runtime and provider packages such as `@purista/harness-openai`.

<div class="callout callout--info">
  <div class="callout__title">AI on normal PURISTA rails</div>
  <p>An attached agent expands into a queue, queue worker, command, and stream. It uses the same service, HTTP, queue, logging, OpenTelemetry, and deployment model as the rest of PURISTA.</p>
</div>

## Execution types

Agents can be defined in three mutually exclusive ways:

| Type | Method | Use case |
|---|---|---|
| **Run function** | `setRunFunction(fn)` | Custom PURISTA logic with direct model, resource, tool, and child-agent access. |
| **Harness agent** | `setHarnessAgent(definition)` | Wrap one reusable `@purista/harness` agent definition. |
| **Harness workflow** | `setHarnessWorkflow(definition)` | Wrap one reusable `@purista/harness` workflow definition. |

You must pick exactly one execution type per agent.

## Model capabilities

Agents declare model aliases and the capabilities they need:

```typescript
.addModel('primary', {
  model: 'gpt-4.1-mini',
  capabilities: ['object', 'text'],
  defaults: { temperature: 0.2 },
})
```

The alias is available as `context.harness.models.primary`. Runtime startup fails when a declared alias is missing or the bound provider does not satisfy the declared capabilities.

## Runtime requirements

Services with attached agents need:

- a `queueBridge`
- `ai.models` runtime bindings for every declared model alias
- provider packages for concrete model backends, such as `@purista/harness-openai`

```typescript
const service = await supportV1ServiceBuilder.getInstance(eventBridge, {
  queueBridge,
  ai: {
    models: {
      primary: {
        provider,
        model: 'gpt-4.1-mini',
        capabilities: ['object'],
      },
    },
  },
})
```

## Session policy

Agents default to an ephemeral session. Use `conversation` mode when a payload field should identify a continuing AI conversation:

```typescript
.setSessionPolicy({
  mode: 'conversation',
  payloadPath: ['conversationId'],
})
```

Keep transport identifiers (`message.id`, `traceId`, `correlationId`) separate from AI conversation identity.

## HTTP response shape

Agents can expose either a simple JSON response or a streamed SSE response:

```typescript
.exposeAsHttpEndpoint('POST', 'agents/support', {
  streamingMode: 'aggregate', // or 'stream'
})
```

For long-running agents, use `setResponseMode('accepted', ...)` so the HTTP call returns a `jobId` and `runId` instead of waiting for the final model result.

## Tools and skills

Agents can call allowlisted commands and child agents:

```typescript
.canInvoke('UserService', '1', 'getUser')
.canInvokeAgent('triageAgent', '1')
.useSkills(['customer-support'])
.useBuiltInTools(false)
```

Keep deterministic business truth in services, commands, stores, resources, queues, and subscriptions. Agent output should become canonical only after deterministic validation and application logic.
