diff --git a/adk/concepts/configuration.mdx b/adk/concepts/configuration.mdx new file mode 100644 index 00000000..5656da60 --- /dev/null +++ b/adk/concepts/configuration.mdx @@ -0,0 +1,250 @@ +--- +title: Configuration +--- + +Configuration defines your agent's identity, models, state schemas, dependencies, and runtime settings. Everything is centralized in `agent.config.ts`. + +## `agent.config.ts` + +The main configuration file uses `defineConfig` from `@botpress/runtime`: + +```typescript +import { z, defineConfig } from "@botpress/runtime"; + +export default defineConfig({ + name: "my-agent", + description: "An AI agent built with the Botpress ADK", + + defaultModels: { + autonomous: "cerebras:gpt-oss-120b", + zai: "cerebras:gpt-oss-120b", + }, + + bot: { + state: z.object({}), + tags: {}, + }, + + user: { + state: z.object({}), + tags: {}, + }, + + conversation: { + tags: {}, + }, + + message: { + tags: {}, + }, + + workflow: { + tags: {}, + }, + + configuration: { + schema: z.object({ + apiKey: z.string(), + maxRetries: z.number().default(3), + }), + }, + + dependencies: { + integrations: { + chat: "chat@0.7.7", + webchat: "webchat@0.3.0", + }, + }, +}); +``` + +## Config options + + + + Agent name. Used to identify your agent in the Botpress dashboard. + + + Optional description of your agent. + + + Default LLM models for your agent. + + + Model used for `execute()` calls in conversations and workflows. + + + Model used for Zai operations (`zai.extract()`, `zai.check()`, etc.). + + + + + Bot-level state schema and tags. See [State](/adk/concepts/state). + + + User-level state schema and tags. See [State](/adk/concepts/state). + + + Conversation-level tags. + + + Message-level tags. + + + Workflow-level tags. + + + Runtime configuration schema. Values are set via `adk config` and accessed at runtime via the `configuration` import. + + + A Zod object schema defining the configuration fields. Must be `z.object()`. + + + + + Integration and interface dependencies. See [Managing Integrations](/adk/managing-integrations). + + + Custom event definitions. Each key is an event name, with an optional schema and description. + + + Evaluation settings. + + + Timeout in seconds for idle eval conversations. + + + Pass threshold for LLM judge assertions (1-5). + + + Model to use for LLM judge assertions (e.g., `"openai:gpt-4o"`). + + + + + +## Accessing configuration at runtime + +Import `configuration` from `@botpress/runtime` to access your agent's configuration values: + +```typescript +import { configuration } from "@botpress/runtime"; + +const apiKey = configuration.apiKey; +const maxRetries = configuration.maxRetries; +``` + +Configuration values are defined by the `configuration.schema` in `agent.config.ts` and set via the `adk config` command or the Botpress dashboard. + + + Configuration is read-only at runtime. Attempting to set a value will throw an error. + + +## Managing configuration + +### Validate configuration + +Run `adk config` to validate all configuration values and set any that are missing: + +```bash +adk config +``` + +```txt +📝 Configuration (development) + +✓ Configuration validated successfully +``` + +This validates your values against the schema and prompts for any missing or invalid fields. Requires a `configuration.schema` in your `agent.config.ts`. + +### Get and set values + +Set and retrieve individual configuration values. Note that `config:get` reads persisted values only and does not resolve schema defaults: + +```bash +adk config:set supportEmail "help@mycompany.com" +``` + +```txt +✓ Configuration updated (development) + supportEmail = help@mycompany.com +``` + +```bash +adk config:get supportEmail +``` + +```txt +📝 Configuration value (development) + + Key: supportEmail + Value: help@mycompany.com +``` + +### Production configuration + +Use the `--prod` flag to manage production configuration separately from development: + +```bash +adk config --prod +adk config:set supportEmail "help@mycompany.com" --prod +adk config:get supportEmail --prod +``` + + + Agent configuration (`adk config`) is separate from integration configuration. Integration settings like API keys are managed in the Control Panel during `adk dev`. See [Managing Integrations](/adk/managing-integrations) for details. + + +## Default models + +The `defaultModels` field sets which LLM models your agent uses: + +```typescript +defaultModels: { + autonomous: "cerebras:gpt-oss-120b", + zai: "cerebras:gpt-oss-120b", +}, +``` + +- **`autonomous`**: used by `execute()` in conversations and workflows +- **`zai`**: used by Zai operations like `zai.extract()`, `zai.check()`, `zai.text()` + +You can override the model per-call using the `model` prop on `execute()`. + +## Custom events + +Define custom events that your agent can emit and listen to: + +```typescript +export default defineConfig({ + name: "my-agent", + events: { + orderPlaced: { + description: "Fired when an order is placed", + schema: z.object({ + orderId: z.string(), + total: z.number(), + }), + }, + }, +}); +``` + +Custom events can be subscribed to in [Triggers](/adk/concepts/triggers) and [Conversations](/adk/concepts/conversations) (via the `events` prop). + +## Dependencies + +The `dependencies` field declares which integrations your agent uses: + +```typescript +dependencies: { + integrations: { + chat: "chat@0.7.7", + webchat: "webchat@0.3.0", + slack: "slack@1.0.0", + }, +}, +``` + +Integration settings (API keys, tokens, etc.) are configured in the Control Panel during `adk dev`, not in `agent.config.ts`. diff --git a/adk/concepts/state.mdx b/adk/concepts/state.mdx new file mode 100644 index 00000000..144a045e --- /dev/null +++ b/adk/concepts/state.mdx @@ -0,0 +1,229 @@ +--- +title: State +--- + +State lets your agent store and reuse data across conversations, users, and the entire bot. The ADK provides three types of states, depending on how long you need the data and who should have access to it. + +## State scopes + +| Scope | Lifetime | Access | Defined in | +|-------|----------|--------|------------| +| Bot | Global, shared across all users and conversations | `bot.state` | `agent.config.ts` | +| User | Per-user, available across all of a user's conversations | `user.state` | `agent.config.ts` | +| Conversation | Per-conversation, scoped to a single conversation | Handler's `state` parameter | Conversation definition | + +## Defining state schemas + +### Bot and user state + +Define bot and user state schemas in `agent.config.ts`: + +```typescript +import { z, defineConfig } from "@botpress/runtime"; + +export default defineConfig({ + name: "my-agent", + + bot: { + state: z.object({ + version: z.number(), + ticketCounter: z.number(), + }).default({ version: 0, ticketCounter: 0 }), + }, + + user: { + state: z.object({ + name: z.string().optional().describe("The user's name"), + department: z.string().optional().describe("The user's department"), + visitCount: z.number().default(0), + }), + }, +}); +``` + + + Use `.default()` to set initial values and `.describe()` to document what each field is for. + + +### Conversation state + +Conversation state is defined on each Conversation definition using the `state` prop: + +```typescript highlight={5-8} +import { Conversation, z } from "@botpress/runtime"; + +export default new Conversation({ + channel: "*", + state: z.object({ + topic: z.string().optional(), + messageCount: z.number().default(0), + }), + handler: async ({ execute, state }) => { + state.messageCount += 1; + + await execute({ + instructions: `You are a helpful assistant. Messages so far: ${state.messageCount}`, + }); + }, +}); +``` + +## Reading and writing state + +### Bot state + +Import `bot` from `@botpress/runtime` to access bot-level state inside any handler, action, tool, or workflow: + +```typescript +import { bot } from "@botpress/runtime"; + +// Read +const counter = bot.state.ticketCounter; + +// Write +bot.state.ticketCounter = counter + 1; +``` + +### User state + +Import `user` from `@botpress/runtime` to access current-user state inside any handler, action, tool, or workflow: + +```typescript +import { user } from "@botpress/runtime"; + +// Read +const name = user.state.name; + +// Write +user.state.visitCount = (user.state.visitCount || 0) + 1; +``` + +### Conversation state + +Conversation state is accessed via the `state` parameter in the handler: + +```typescript highlight={6-8} +export default new Conversation({ + channel: "*", + state: z.object({ + phase: z.string().default("greeting"), + }), + handler: async ({ state, execute }) => { + if (state.phase === "greeting") { + state.phase = "main"; + } + + await execute({ + instructions: `Current phase: ${state.phase}`, + }); + }, +}); +``` + + + State changes are handled automatically. You don't need to call a save method, just update the state object directly. + + +## Tags + +Tags are string key-value pairs you can attach to bots, users, conversations, messages, and workflows. They're useful for categorization, filtering, and querying. + +### Defining tags + +Define tag schemas in `agent.config.ts`: + +```typescript +export default defineConfig({ + name: "my-agent", + + bot: { + tags: { + environment: { title: "Environment", description: "Current deployment environment" }, + }, + }, + + user: { + tags: { + role: { title: "Role", description: "User's role in the organization" }, + }, + }, + + conversation: { + tags: { + priority: { title: "Priority", description: "Conversation priority level" }, + }, + }, +}); +``` + +### Reading and writing tags + +Bot and user tags are read and written the same way as state: + +```typescript +import { bot, user } from "@botpress/runtime"; + +// Bot tags +bot.tags.environment = "production"; +const env = bot.tags.environment; + +// User tags +user.tags.role = "admin"; +``` + +You can access conversation tags via the `conversation` instance: + +```typescript +export default new Conversation({ + channel: "*", + handler: async ({ conversation, execute }) => { + // Read + const priority = conversation.tags.priority; + + // Write + conversation.tags.priority = "high"; + }, +}); +``` + +System tags set by integrations (containing `:` in the key) are read-only: + +```typescript +// You can read system tags +const owner = conversation.tags["webchat:owner"]; + +// But writes to system tags are silently ignored +conversation.tags["webchat:owner"] = "new-value"; // no effect +``` + +## State references + +You can store workflow instances in state. They are saved automatically and loaded back as full instances when read: + +```typescript highlight={7, 11} +import { Conversation, Reference, z } from "@botpress/runtime"; +import OnboardingWorkflow from "../workflows/onboarding"; + +export default new Conversation({ + channel: "*", + state: z.object({ + activeWorkflow: Reference.Workflow("onboarding").optional(), + }), + handler: async ({ state }) => { + if (!state.activeWorkflow) { + state.activeWorkflow = await OnboardingWorkflow.start({}); + } + }, +}); +``` + +## Bot and user identity + +The `bot` and `user` objects also expose an `id` property: + +```typescript +import { bot, user } from "@botpress/runtime"; + +const botId = bot.id; +const userId = user.id; +``` diff --git a/docs.json b/docs.json index 3da6a127..28f711cc 100644 --- a/docs.json +++ b/docs.json @@ -104,7 +104,9 @@ "/adk/concepts/tables", "/adk/concepts/triggers", "/adk/concepts/knowledge", - "/adk/concepts/tools" + "/adk/concepts/tools", + "/adk/concepts/state", + "/adk/concepts/configuration" ] }, "/adk/managing-integrations",