Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ ruff = "*"
pre-commit = "*"
the-agent = {path = ".", editable = true}
pytest-xdist = "*"
virtualenv = "==21.14.5"

[requires]
# Python 3.12: keep in sync with pyproject.toml
Expand Down
1,920 changes: 1,018 additions & 902 deletions Pipfile.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion alembic.ini
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ script_location = ./src/db/alembic

# sys.path path, will be prepended to sys.path if present.
# defaults to the current working directory.
prepend_sys_path = .src
prepend_sys_path = ./src

# timezone to use when rendering the date within the migration file
# as well as the filename.
Expand Down
43 changes: 29 additions & 14 deletions docker/.env
Original file line number Diff line number Diff line change
@@ -1,20 +1,35 @@
# Minimal configuration for local Docker testing
# For production, set proper values for all secrets
# local-only example values; replace secrets before deploying

# Database (required)
POSTGRES_HOST=db
POSTGRES_DB=agent
POSTGRES_USER=root
POSTGRES_PASS=root
POSTGRES_PASSWORD=root
POSTGRES_USER=agent
POSTGRES_PASS=local-db-password

# API Authentication (required)
API_KEY=developer
SHLINK_DB_NAME=shlink
SHLINK_DB_USER=shlink
SHLINK_DB_PASSWORD=local-shortener-db-password
SHLINK_PORT=8081
SHLINK_DOMAIN=localhost:8081
SHLINK_HTTPS_ENABLED=false
URL_SHORTENER_BASE_URL=http://shortener:8080
URL_SHORTENER_API_KEY=local-shortener-key

# Path configuration (required for Docker)
API_PORT=8080
API_KEY=local-api-key
JWT_SECRET_KEY=local-jwt-secret-change-me
TOKEN_ENCRYPT_SECRET=local-encryption-secret-change-me
PUBLIC_API_BASE_URL=http://localhost:8080
BACKOFFICE_URL_BASE=http://localhost:5173
WEBSITE_URL=http://localhost:5173
PARENT_ORGANIZATION="Example Organization"
THE_AGENT_ISSUES_REPO=appifyhub/agent-backend
THE_AGENT_ISSUE_TEMPLATES_PATH=/app/src/templates

# Optional: Override defaults if needed
# LOG_LEVEL=debug
# MAX_USERS=100
# WEBSITE_URL=https://the-agent.appifyhub.com
# leave S3 and Uploadcare unconfigured to use the persistent local attachment volume
S3_BASE_URL=
UPLOADCARE_PUBLIC_KEY=
UPLOADCARE_PRIVATE_KEY=

# add provider keys and integration credentials from src/util/config.py as needed
# PLATFORM_OPEN_AI_KEY=
# TELEGRAM_BOT_TOKEN=

32 changes: 17 additions & 15 deletions docker/README.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,37 @@
## Docker Compose support

This project can run in the Docker Compose framework.
This project can run in Docker Compose with its database and URL shortener. Attachments use persistent local storage by default, so a separate object-storage service is not required.

The basic `Dockerfile` is available in the project's root directory. To run the service using Docker Compose, you need a `docker-compose.yml` file, which is provided here.
### Start and stop

The basic command to run the configured image is:
Run these commands from the project root:

```console
$ docker compose up
docker compose --env-file docker/.env -f docker/docker-compose.yml -p agent-local up -d --wait
docker compose --env-file docker/.env -f docker/docker-compose.yml -p agent-local down
```

When you don't need the service anymore, you can just tear it down:
If Compose is installed as a standalone binary, use `docker-compose` instead of `docker compose`.

```console
$ docker compose down
```
Stopping the stack preserves its named volumes. Adding `--volumes` to `down` deletes the stored data.

### How does the local Docker build work?

The build copies over the necessary files into the image, then runs the run script from within. Depending on how your storage is configured, this may pull the necessary dependencies before running.

Docker is not a development environment, therefore no tests will be executed during Docker builds. It's assumed that you're running Docker as the last step of your development process.
The basic `Dockerfile` is available in the project's root directory. It copies the necessary files into the image and installs the dependencies; tests are not executed during builds.

The latest image is available in Docker Hub and will be tagged with `appifyhub/the-agent:latest`.
Compose uses the published `appifyhub/the-agent:latest` image by default.

### How do I reconfigure the project properties?

The directory here contains a `.env` file containing configurable build properties. There are sensible defaults that you can change by simply editing the `.env` file. If running the project from your machine directly, normal environment variables will be used.
This directory contains a `.env` file with generic local examples. Edit it to configure the stack and supply credentials for the integrations you use.

Exported shell variables can override these examples. Keep signing and encryption secrets stable when reusing stored data.

Database initialization runs only for new volumes. Back up existing data before changing database versions, credentials, or storage settings.

### Word of caution

It goes without saying, but let's say it anyway:
These defaults are for local testing and bind exposed services to loopback. Remote integrations need publicly reachable URLs.

**DO NOT** deploy these example settings directly to production or production-like environments.

**DO NOT** deploy any of this directly to production or production-like environments. All of the files provided here are for testing only and should not be used when deploying to real environments and real users.
58 changes: 53 additions & 5 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,32 +1,80 @@
services:
db:
image: postgres:alpine
image: postgres:17.9-alpine
container_name: the-agent-database
restart: always
env_file:
- .env
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASS}
SHLINK_DB_NAME: ${SHLINK_DB_NAME}
SHLINK_DB_USER: ${SHLINK_DB_USER}
SHLINK_DB_PASSWORD: ${SHLINK_DB_PASSWORD}
volumes:
- postgres:/var/lib/postgresql/data
- ./init-shlink-db.sh:/docker-entrypoint-initdb.d/init-shlink-db.sh:ro
expose:
- 5432
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
test: ["CMD-SHELL", "pg_isready -h 127.0.0.1 -U $$POSTGRES_USER -d $$POSTGRES_DB"]
interval: 5s
timeout: 5s
retries: 15

shortener:
image: shlinkio/shlink:4.5.2
restart: always
environment:
DEFAULT_DOMAIN: ${SHLINK_DOMAIN}
IS_HTTPS_ENABLED: ${SHLINK_HTTPS_ENABLED}
INITIAL_API_KEY: ${URL_SHORTENER_API_KEY}
DB_DRIVER: postgres
DB_HOST: db
DB_NAME: ${SHLINK_DB_NAME}
DB_USER: ${SHLINK_DB_USER}
DB_PASSWORD: ${SHLINK_DB_PASSWORD}
depends_on:
db:
condition: service_healthy
ports:
- "127.0.0.1:${SHLINK_PORT}:8080"
healthcheck:
test: ["CMD", "php", "-r", "exit(@file_get_contents('http://127.0.0.1:8080/rest/health') === false ? 1 : 0);"]
interval: 10s
timeout: 5s
retries: 15
start_period: 30s

api:
image: appifyhub/the-agent:latest
container_name: the-agent-api
restart: always
env_file:
- .env
environment:
POSTGRES_HOST: db
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASS: ${POSTGRES_PASS}
URL_SHORTENER_API_KEY: ${URL_SHORTENER_API_KEY}
volumes:
- attachments:/app/.local/s3
depends_on:
db:
condition: service_healthy
shortener:
condition: service_healthy
ports:
- "80:80"
- "127.0.0.1:${API_PORT}:80"
healthcheck:
test: ["CMD", "pipenv", "run", "python", "-c", "from urllib.request import urlopen; urlopen('http://127.0.0.1/health', timeout=5).close()"]
interval: 10s
timeout: 10s
retries: 15
start_period: 30s

volumes:
postgres:
driver: local
attachments:
driver: local
13 changes: 13 additions & 0 deletions docker/init-shlink-db.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/sh
set -eu

psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" \
--set ON_ERROR_STOP=1 \
--set shlink_db="$SHLINK_DB_NAME" \
--set shlink_user="$SHLINK_DB_USER" \
--set shlink_password="$SHLINK_DB_PASSWORD" <<'SQL'
CREATE ROLE :"shlink_user" LOGIN PASSWORD :'shlink_password';
CREATE DATABASE :"shlink_db" OWNER :"shlink_user";
REVOKE CONNECT ON DATABASE :"shlink_db" FROM PUBLIC;
SQL

12 changes: 11 additions & 1 deletion docs/open-api-docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ openapi: 3.0.3
info:
title: The Agent's user-facing API
description: The user-facing parts of The Agent's API service (excluding system-level endpoints, chat completion, maintenance endpoints, etc.)
version: 5.38.4
version: 5.39.1
license:
name: MIT
url: https://opensource.org/licenses/MIT
Expand Down Expand Up @@ -1325,6 +1325,10 @@ components:
type: boolean
nullable: false
description: Whether to apply this user's custom prompt instructions in agent interactions for this chat
split_messages:
type: boolean
nullable: false
description: Whether to split this user's replies into separate messages at paragraph boundaries in this chat; platform message-length limits still apply when disabled
max_output_tokens:
type: integer
nullable: false
Expand All @@ -1343,6 +1347,7 @@ components:
required:
- use_about_me
- use_custom_prompt
- split_messages

ChatSettingsResponse:
type: object
Expand Down Expand Up @@ -1428,6 +1433,10 @@ components:
type: boolean
nullable: false
description: Whether this user's custom prompt instructions are applied in agent interactions for this chat
split_messages:
type: boolean
nullable: false
description: Whether this user's replies are split into separate messages at paragraph boundaries in this chat; platform message-length limits still apply when disabled
max_output_tokens:
type: integer
nullable: false
Expand All @@ -1446,6 +1455,7 @@ components:
required:
- use_about_me
- use_custom_prompt
- split_messages
- max_output_tokens
- max_chat_history_depth
- max_iterations
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-10-09
Loading
Loading