Project Overview

Development Setup

Prerequisites

Requirement Notes

JDK 21

The Gradle toolchain targets Java 21. Later JDKs can run the build as long as the toolchain resolves a 21 JDK.

Gradle

Not needed separately — use the wrapper (./gradlew), which pins the supported version.

Docker with Compose

Runs the local infrastructure stack (MongoDB, Elasticsearch, Neo4j, Keycloak, MinIO, telemetry).

ffmpeg

Required by the engine for media conversion. It must be reachable at the path configured by promethist.resource.ffmpeg-path (default /usr/local/bin/ffmpeg).

Provider credentials

A language model provider and, for spoken conversations, a TTS/STT provider. Without them the engine starts but cannot conduct a conversation.

Node.js

Only needed to build this documentation site locally.

Install the KtLint pre-commit hook once after cloning:

./gradlew ktlintCopyPreCommitHook

Building

# everything
./gradlew clean build

# a single module
./gradlew :promethist-engine:build

Module Gradle paths carry the promethist- prefix: :promethist-lib, :promethist-common, :promethist-client, :promethist-engine, :promethist-bridge, :promethist-relay.

Running the Engine

./gradlew :promethist-engine:bootRun

The engine listens on 9010 (HTTP, REST API, WebSocket) and 9011 (Socket.IO). Its defaults are in engine/src/main/resources/application.properties and expect the local infrastructure stack on the ports listed below.

Environment-specific settings and credentials belong in an additional properties file rather than in the checked-in defaults — the repository keeps such files under local/ (for example local/default/application-default.properties). Point Spring at one with:

./gradlew :promethist-engine:bootRun \
  --args="--spring.config.additional-location=file:local/default/application-default.properties"

Some integrations are additionally configured through environment variables:

Variable Required Description

AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY

For AWS providers

Credentials for Amazon Polly, Amazon Transcribe and S3 storage.

AZURE_STORAGE_KEY

For Azure storage

Shared key of the Azure Storage account when promethist.storage.type=azure.

GOOGLE_APPLICATION_CREDENTIALS

For Google providers

Path to the service account key file used by Google speech services.

Local Infrastructure

The docker-compose.yaml in the repository root runs the supporting services. Create the data directories it mounts before the first start — persistent local data is kept under data/:

mkdir -p data/postgres
docker compose up -d

The services: section at the end of the compose file selects what actually starts; comment out what you do not need, and uncomment what you do. MongoDB is commented out by default, so enable it (or run your own instance on port 9417) before starting the engine.

The compose file can also build and run the engine image itself, which requires the distribution archive produced by the Gradle build:

./gradlew build
docker compose build engine
docker compose up engine

Local Port Map

Service Port Purpose

Engine HTTP

9010

REST API, plain WebSocket and Twilio WebSocket endpoints.

Engine Socket.IO

9011

Conversation transport for web and mobile clients.

Relay Socket.IO

9012

Relay service.

Bridge HTTP

9013

Bridge test service.

Grafana

9300

Dashboards over the local telemetry stack.

OTel collector

9317 (gRPC), 9318 (HTTP)

Trace, metric and log ingestion.

Prometheus

9390

Metrics storage.

Tempo

9217 (gRPC), 9232 (HTTP)

Trace storage.

MongoDB

9417

Primary data store.

PostgreSQL

9432

Keycloak database.

Keycloak

9400

Identity provider, JWT issuer.

Kibana

9480

Elasticsearch UI.

Elasticsearch

9481

Memory, embeddings and indexes.

MinIO

9490 (console), 9491 (S3 API)

S3-compatible object storage.

Neo4j

9787 (Bolt), 9774 (browser)

Knowledge graph.

Tests

# unit tests of a module
./gradlew :promethist-engine:test

# a single test class
./gradlew :promethist-engine:test --tests "ai.promethist.engine.pipeline.RelativeTimeCalculatorTest"

# integration tests (classes matching **/*IntegrationTest.*)
./gradlew :promethist-engine:integrationTests

Integration tests talk to real infrastructure and providers, so they need the local stack running and valid credentials. In CI they are a manual job.

Conversation-level testing against a running engine — including real devices and browsers — is what the Bridge is for.

Trying a Conversation

The quickest check that a locally running engine can hold a conversation is the HTTP pipeline channel:

curl -s -c session.txt "http://localhost:9010/api/pipeline/agent:default?text=%23intro"

curl -s -b session.txt -X PUT "http://localhost:9010/api/pipeline/agent:default" \
  -H "Content-Type: text/plain" \
  -H "X-Device-Id: dev-box" \
  --data-binary "What time is it?"

agent:default is a pipeline key — replace default with the ref of an agent that exists in your database. See HTTP Pipeline Channel for the full semantics, and Reference CLI Client for a client that also does audio.

The test/engine/*.http files in the repository contain ready-made requests for the REST API that can be executed directly from IntelliJ IDEA.

Telemetry

To run with the OpenTelemetry agent attached:

export JAVA_TOOL_OPTIONS=-javaagent:lib/opentelemetry-javaagent.jar
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:9317

Traces and metrics then appear in the local Grafana instance on port 9300.

Adding a Component to the Engine

Spring only discovers engine components in the packages listed in the @ComponentScan of EngineConfiguration — ai.promethist..configuration, ai.promethist..controller, ai.promethist..component and ai.promethist..service. Place new beans accordingly; note that the wildcard means components from common and lib are picked up as well.

A component that needs a dependency only at runtime must either be added to the engine’s runtimeOnly dependencies, or its jars placed in the lib/ subdirectory of the distribution.