# App Configuration

Configure your Agentuity project

Agentuity projects use minimal configuration. Most setup happens in code, not config files.

## agentuity.json

The project configuration file:

```json
{
  "projectId": "proj_...",
  "orgId": "org_...",
  "region": "use"
}
```

No agent definitions, no trigger configurations. Those live in your code.

## app.ts

The app entry point wires agents, routes, and configuration together:

```typescript
import { createApp } from '@agentuity/runtime';
import agents from './src/agent';
import api from './src/api';

const app = await createApp({
  router: { path: '/api', router: api },
  agents,
  analytics: true,
});

app.logger.debug('Running %s', app.server.url);

export default app;
```

### With Startup and Cleanup Logic

Initialize shared resources in modules or startup code, then register cleanup with `registerShutdownHook()`:

```typescript
import { createApp, registerShutdownHook } from '@agentuity/runtime';

const db = await connectDatabase();

registerShutdownHook(async () => {
  await db.close();
});

const app = await createApp({
  router: { path: '/api', router: api },
  agents,
});

app.logger.debug('Running %s', app.server.url);

export default app;
```

### With Additional Options

```typescript
import { createApp } from '@agentuity/runtime';
import agents from './src/agent';
import api from './src/api';

const app = await createApp({
  router: { path: '/api', router: api },
  agents,

  // CORS configuration
  cors: {
    sameOrigin: true,
    allowedOrigins: ['https://myapp.com'],
  },

  // Response compression (gzip/deflate)
  compression: {
    threshold: 1024, // Compress responses larger than 1KB (default)
  },

  // Custom storage implementations (optional)
  services: {
    keyvalue: myCustomKV,
    vector: myCustomVector,
  },
});

export default app;
```

#### Compression Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `enabled` | `boolean` | `true` | Enable/disable compression |
| `threshold` | `number` | `1024` | Minimum response size (bytes) to compress |
| `filter` | `(c) => boolean` | - | Custom filter function |

Compression automatically bypasses WebSocket upgrades and requests without `Accept-Encoding` headers.

### Event Listeners

Listen for agent lifecycle events using the top-level `addEventListener`:

```typescript
import { addEventListener } from '@agentuity/runtime';

addEventListener('agent.started', (eventName, agent, ctx) => {
  ctx.logger.info('Agent started', { name: agent.metadata.name });
});

addEventListener('agent.completed', (eventName, agent, ctx) => {
  ctx.logger.info('Agent completed', { session: ctx.sessionId });
});
```

## Build Configuration

Use `vite.config.ts` for build settings (plugins, entry point, rollup options). Runtime settings like analytics and service configuration belong in `createApp()`.

```typescript title="vite.config.ts"
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';
import { defineConfig } from 'vite';
import { join } from 'node:path';

export default defineConfig({
  plugins: [react(), tailwindcss()],
  root: '.',
  build: {
    rollupOptions: {
      input: join(import.meta.dirname, 'src/web/index.html'),
    },
  },
});
```

> [!NOTE]
> **When to Customize**
> Most projects only need to change `plugins` in `vite.config.ts`. The default template includes React and Tailwind CSS. Replace them with your framework of choice (e.g., `@sveltejs/vite-plugin-svelte`).

See the [reference page](/reference/cli/build-configuration) for all options and examples.

## Configuring Deployment and Build Resources

Configure how your project runs and builds in the cloud using the `deployment` and `build` sections of `agentuity.json`.

### deployment

The `deployment` section controls resources allocated when your project is handling requests, and any custom domains:

- `deployment.resources`: CPU, memory, and disk allocated to the running service
- `deployment.domains`: custom domains attached to the project

### build

The `build` section controls the sandbox where your project compiles during cloud deployment:

- `build.timeout`: maximum time allowed for the build (e.g., `"30m"`)
- `build.resources`: memory, CPU, and disk for the build sandbox

```json
{
  "projectId": "proj_...",
  "orgId": "org_...",
  "region": "use",
  "deployment": {
    "resources": {
      "cpu": "500m",
      "memory": "500Mi",
      "disk": "500Mi"
    },
    "domains": []
  },
  "build": {
    "timeout": "30m",
    "resources": {
      "memory": "4Gi",
      "cpu": "2",
      "disk": "4Gi"
    }
  }
}
```

`deployment.resources` controls what your service gets when handling requests. `build.resources` controls the isolated sandbox where your project compiles. Increase build resources if you have large dependencies or complex compilation steps.

For detailed options, see [Deploying to the Cloud](/reference/cli/deployment#resource-configuration).

### Running Deploy Lifecycle Scripts

Run custom steps before or after deployment using `predeploy` and `postdeploy` scripts in `package.json`:

```json title="package.json"
{
  "scripts": {
    "predeploy": "cd ../.. && bun install && bun run build:packages",
    "deploy": "agentuity deploy",
    "postdeploy": "echo 'Deploy complete'"
  }
}
```

When deploying via the [Agentuity GitHub App](/reference/github-app#build-process), defining `predeploy` gives you full control over the install step. Without it, the platform runs `bun install` automatically. See [Running Deploy Lifecycle Scripts](/reference/cli/deployment#running-deploy-lifecycle-scripts) for the full reference.

## Environment Variables

```bash
# Required
AGENTUITY_SDK_KEY=...        # API key for Agentuity services

# Optional
AGENTUITY_LOG_LEVEL=info     # trace, debug, info, warn, error
PORT=3500                    # Dev server port (default: 3500)

# Resource Credentials (auto-added by CLI when creating resources)
DATABASE_URL=postgresql://...   # Added by: agentuity cloud db create
# S3 credentials                # Added by: agentuity cloud s3 create
# REDIS_URL=redis://...         # From: agentuity cloud redis show

# LLM Provider Keys (optional; if using your own API keys instead of the AI Gateway)
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...

# Frontend-accessible (exposed to browser)
AGENTUITY_PUBLIC_API_URL=... # Any of these prefixes work:
VITE_MY_VAR=...              # - AGENTUITY_PUBLIC_*
PUBLIC_MY_VAR=...            # - VITE_*
                             # - PUBLIC_*
```

> [!NOTE]
> **AI Gateway**
> If you don't set provider API keys, LLM requests are routed through the Agentuity AI Gateway using your SDK key. This provides unified billing and monitoring.

> [!WARNING]
> **Public Environment Variables**
> Environment variables prefixed with `AGENTUITY_PUBLIC_`, `VITE_`, or `PUBLIC_` are exposed to the frontend bundle and visible in the browser. Never put secrets or API keys in these variables.

### Environment-Specific Files

Use separate `.env` files instead of commenting/uncommenting variables when switching between local development and deployed contexts.

**File loading order today:**

| Mode | Files checked |
|------|---------------|
| `agentuity dev` / local profile | `.env.{profile}` → `.env.development` → `.env` |
| Production build or non-local profile | `.env.{profile}` → `.env` → `.env.production` |

Files loaded later in the chain override earlier ones. For `agentuity dev`, the order is `.env.{profile}` then `.env.development` then `.env`, so `.env` wins when keys conflict. For deployed or non-local profiles, the order is `.env.{profile}` then `.env` then `.env.production`, so `.env.production` wins.

Profile-specific files use the active CLI profile. See [CLI Profiles](/reference/cli/profiles) for switching profiles and profile-specific defaults.

**Example setup:**

```bash title=".env"
# Shared defaults loaded in development and production
AGENTUITY_SDK_KEY=sdk_...
OPENAI_API_KEY=sk-...
AGENTUITY_PUBLIC_API_URL=https://your-project.agentuity.run
```

```bash title=".env.development"
# Development-only values
DEBUG=true
TRUSTED_ORIGINS=http://localhost:3000
```

> [!NOTE]
> **Separate Files, Not Comments**
> Instead of commenting out lines when switching contexts, put shared defaults in `.env` and values that only exist in local development in `.env.development`. Be careful with duplicate keys: the CLI loads `.env.development` before `.env`, so `.env` (loaded last) wins when both define the same variable.

**Additional files:**

- **`.env.local`**: Bun may use this for app runtime behavior, but the Agentuity CLI does not currently include `.env.local` when it searches for `AGENTUITY_SDK_KEY` during `agentuity dev` or deploy preflight. Keep required CLI credentials in one of the files listed above.

**Git behavior:** The default `.gitignore` ignores `.env`. Other env files (`.env.development`, `.env.local`, profile-specific files) are not ignored by default. Add any files containing secrets to your `.gitignore`.

## Infrastructure as Code

Unlike traditional platforms, Agentuity defines infrastructure in your route files:

```typescript
// src/api/index.ts
import { Hono } from 'hono';
import type { Env } from '@agentuity/runtime';
import { websocket } from '@agentuity/runtime';
import chatHandler from '@agent/chat/agent';

const api = new Hono<Env>()
  // Standard HTTP endpoint
  .post('/cleanup', async (c) => {
    return c.text('OK');
  })
  // WebSocket endpoint
  .get('/chat', websocket((c, ws) => {
    ws.onMessage(async (event) => {
      const result = await chatHandler.run({ message: event.data as string });
      ws.send(JSON.stringify(result));
    });
  }));

export default api;
```

This approach means:
- **Deployments are self-contained**: rolling back restores exact configuration
- **Version control**: your infrastructure changes are tracked in Git
- **No config drift**: what's in code is what runs

## Next Steps

- [HTTP Routes](/routes/http): Define HTTP endpoints
- [Schedules](/services/schedules): Run recurring tasks
- [AI Gateway](/agents/ai-gateway): Configure LLM providers