Agentic Engineer – AI Chat Assistant¶
Agentic Engineer is an optional AI-powered chat assistant built into ubTrace. It lets users ask natural-language questions about their traceability data and get answers backed by real graph queries against the parqour graph engine.
Note
Agentic Engineer is an optional feature, disabled by default, and requires an LLM provider to be configured.
The shipped default provider is a cloud service. With
COPILOT_LLM_PROVIDER=openrouter (the default used by every example in
this document), the questions users ask and the traceability content the
assistant retrieves to answer them — requirement titles and descriptions,
need ids, document structure and document text — are sent to OpenRouter, a
third-party US-hosted API router.
For a deployment where no data may leave your infrastructure, use
COPILOT_LLM_PROVIDER=openai-compatible pointed at an inference server
you host. See self-hosted inference below.
Architecture¶
Frontend / Admin (CopilotKit sidebar)
|
v
ub-copilot (NestJS, port 4000)
|--- LLM Provider (OpenAI / OpenAI-compatible / OpenRouter / Anthropic / Google / Azure)
|--- ubTrace API (REST data + graph PDP)
| |--- /v1/graph/* -> parqour graph engine (HTTP, port 7190)
|--- PostgreSQL (conversation persistence)
The copilot runs as a separate container (ub-copilot) alongside the API,
worker, and frontend. It uses LangChain chat model integrations so that LLM
providers can be switched via configuration alone.
Enabling Agentic Engineer¶
Docker Compose¶
Set these variables in your .env file:
# Enable Agentic Engineer chat sidebar
UBAI_ENABLED=true
# LLM provider configuration
COPILOT_LLM_PROVIDER=openrouter
COPILOT_LLM_MODEL=google/gemini-3.8-flash
COPILOT_LLM_API_KEY=<your-api-key>
COPILOT_LLM_BASE_URL=
# The parqour graph engine is enabled by UBAI_ENABLED above -- the assistant
# cannot answer graph questions without it, so there is no separate switch.
PARQOUR_URL=http://ubtrace-parqour:7190
# Production: keep authz on and share the SAME key with the API.
PARQOUR_AUTHZ_ENABLED=true
PARQOUR_AUTHZ_SIGNING_KEY=<long-random-shared-secret>
Then start with make up. The copilot service and the parqour graph engine
are activated automatically (via the ubai profile) when the flags above are
set.
Kubernetes / Helm¶
ubai.enabled is the single switch. It deploys both the copilot service
and the parqour graph engine — the assistant cannot answer graph questions
without the engine, so there is no separate switch for it.
Enabling it makes two secrets mandatory, and the chart refuses to render without them rather than installing and then crash-looping:
copilot.config.apiToken— the copilot’s service token for calling the ubTrace API. Must start withcpt_and be at least 32 characters:echo "cpt_$(openssl rand -hex 32)"
parqour.authz.signingKey— shared between the API and the graph engine so the engine can verify the access grants the API issues. At least 32 characters:openssl rand -hex 32
parqour.sidecarHmacKey— the graph engine’s own cache-authentication key. The engine refuses to start without it, whether or not that cache is enabled. At least 32 characters, and a different value from the signing key above (that one is shared with the API; this one never leaves the engine):openssl rand -hex 32
In your Helm values file:
ubai:
enabled: true
copilot:
config:
llmProvider: "openrouter"
llmModel: "google/gemini-3.8-flash"
llmApiKey: "<your-api-key>"
apiToken: "cpt_0000000000000000000000000000000000000000000000000000000000000000"
parqour:
maxInstances: 10
authz:
enabled: true
signingKey: "0000000000000000000000000000000000000000000000000000000000000000"
sidecarHmacKey: "1111111111111111111111111111111111111111111111111111111111111111"
All three values above are placeholders of the right shape — replace them with the
output of the commands above. To keep them out of a values file altogether,
create a Secret carrying copilot-api-token,
parqour-authz-signing-key and parqour-sidecar-hmac-key and pass --set
global.existingSecret=<name>; see ubtrace-secret-example.yaml in the
chart directory.
Then deploy with:
helm upgrade --install ubtrace ./charts/ubtrace-*.tgz \
-f ./charts/values.yaml \
-f ./my-ubai-values.yaml
LLM Provider Configuration¶
Agentic Engineer supports six LLM providers — openai, anthropic,
google, azure-openai, openai-compatible, and openrouter. Select
one with COPILOT_LLM_PROVIDER (Docker Compose) or
copilot.config.llmProvider (Helm), and set the model with
COPILOT_LLM_MODEL.
The models below are curated recommendations, grouped by the trade-off they optimise. “Tested” models have been validated against the ubTrace workflows; the others are good starting points for the stated priority.
Tier |
Optimises |
Model |
|
|---|---|---|---|
Tested |
– |
Gemini 3.8 Flash |
|
Tested |
– |
GLM 5.3 Flash |
|
Recommended |
Speed + Quality |
Gemini 3.8 Flash |
|
Recommended |
Speed + Cost |
DeepSeek V4.1 Flash |
|
Recommended |
Quality + Cost |
GLM 5.3 Flash |
|
Alternatives |
Quality (medium speed & cost) |
Claude Sonnet 5 |
|
Alternatives |
Quality + Cost |
GPT-5.6 Luna |
|
OpenAI-compatible Setup¶
Use openai-compatible for providers that expose an OpenAI-compatible chat
completions API.
COPILOT_LLM_PROVIDER=openai-compatible
COPILOT_LLM_MODEL=<provider-model-name>
COPILOT_LLM_API_KEY=<provider-api-key-if-required>
COPILOT_LLM_BASE_URL=https://provider.example/v1
This is also the path for fully self-hosted, open-source inference. Any FOSS
engine that exposes an OpenAI-compatible /v1 chat completions endpoint works
today, keeping all data on your own infrastructure:
llama.cpp (
llama-server) and vLLM – pointCOPILOT_LLM_BASE_URLat the server’s/v1endpoint; leaveCOPILOT_LLM_API_KEYunset if the server does not require one.
parqour Configuration¶
parqour is a graph engine that answers traceability queries (needs, documents,
sections, and their relationships) directly from the parquet + schema.json
files the worker writes into the output directory. It mounts that directory
read-only and lazily loads on the first query — there is no import step, no
bolt protocol, and no per-slot pods. The API is the graph PDP and proxies
/v1/graph/* to the engine over HTTP (port 7190).
Variable |
Default |
Description |
|---|---|---|
|
|
URL the API uses to reach the engine. |
|
|
Max concurrently-loaded graph instances in memory. |
|
|
Max records returned per query. |
|
|
Per-query timeout in milliseconds. |
|
|
Engine verifies the API-minted signed grant (required in production). |
|
(empty) |
Shared HS256 key; set the SAME value on the API and the engine. |
|
|
TTL of the minted grant, in seconds. |
|
|
Cache graph query results in Redis so the assistant does not re-execute a query it already ran (across sibling agents and turns). Off by default: results are permission-filtered per user inside the engine, so an operator opts in deliberately. |
|
|
Lifetime of a cached result. Capped at |
|
|
Results larger than this are not cached. |
Versions Without a Graph Export¶
The parquet files parqour reads are written by the worker during processing,
so a version processed while UBAI_ENABLED=false has no
output/<org>/<project>/<version>/parquet_exports/ directory at all.
Such a version is not simply empty, and the assistant does not treat it as such:
asking about it answers This version has no graph export, so the assistant
cannot query it. Re-ingest the version with ubAI enabled to create one. – a
different answer from “nothing in this version matches your question”, which is
what an empty graph would mean.
To create the export, re-ingest the version (upload it again for the same
organization, project and version) with UBAI_ENABLED=true. No other state
needs to be reset, and versions that already have an export are unaffected.
Conversation Persistence¶
Chat conversations are stored in PostgreSQL (the same database as the rest of ubTrace). Each conversation is a thread with messages, and a thread can be renamed or deleted from the chat panel.
Troubleshooting¶
Copilot container not starting:
# Check logs
docker logs ubtrace-copilot --tail 20
# Verify health
curl http://localhost:4000/api/v1/copilot/health
OpenAI-compatible provider not reachable from Docker:
# Verify the provider endpoint is reachable from the container
docker exec ubtrace-copilot \
wget -qO- https://provider.example/v1/models
parqour not answering graph queries:
# Check the engine is healthy. Port 7190 is not published to the host in a
# production deployment -- the API is the engine's only client and reaches it
# over the internal network -- so probe it from inside the container.
docker compose exec ubtrace-parqour curl -fsS http://127.0.0.1:7190/health
# Confirm the worker generated parquet + schema.json for the version.
# An absent directory means the version was ingested with ubAI disabled --
# re-ingest it with UBAI_ENABLED=true (see "Versions Without a Graph Export").
docker logs ubtrace-worker --tail 50 | grep -i parqour
ls output/<org>/<project>/<version>/parquet_exports/
# Check the API's graph PDP proxy (the ub-backend/ub-api container that
# mints grants and proxies /v1/graph/* to the engine; requires UBAI_ENABLED)
docker logs ubtrace-api --tail 50 | grep -iE 'graph|parqour'
# Check the engine itself (separate ubtrace-parqour container)
docker logs ubtrace-parqour --tail 50