Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Thilke System Handbook

Thilke is an agentic development platform for turning issues, repositories, runtime context, and human approvals into durable, recoverable software changes.

The system splits source of truth across Gitea for code and issues, Thilke Agent for durable execution, Jujutsu for recoverable VCS, GraphRAG and memory for context, and Multica for UI and ingress.

This handbook is built with mdBook and published at https://docs.thilke.com.

Principles

Agentic first

Thilke favors structured context, durable artifacts, reversible operations, and approval-gated writes over opaque chat transcripts.

FOSS-first

Core pieces should be FOSS where practical: Rust, ADK-Rust, Ratatui, Jujutsu, SQLite, Gitea, mdBook, Traefik, Caddy, and nginx. Provider-specific model access is isolated behind adapters.

Durable by default

Every run should leave enough state to resume or audit it later: prompt, issue context, tool proposals, approvals, events, branch metadata, validation output, and PR links.

System Architecture

User or schedule -> Gitea issue / Multica event -> thilke-agentd plan-issue -> GraphRAG + memory -> ADK-Rust planner -> proposed-actions.json -> TUI/API approval -> execute-approved -> jj branch, validation, commit, push, PR, issue comment

git.thilke.com is the canonical source forge, control.thilke.com exposes Multica, and docs.thilke.com publishes this handbook. Core services currently run on 5.78.191.210.

Services and Endpoints

ServicePurposeBindPublic route
thilke-agentdDurable ADK-Rust agent runtime127.0.0.1:7817internal
thilke-codex-gatewayOpenAI-compatible gateway to Codex auth127.0.0.1:8092internal
thilke-pathway-contextGraphRAG and memory API127.0.0.1:8090internal
thilke-multica-bridgeMultica sync and ingress adapter127.0.0.1:8093internal
thilke-docsStatic mdBook sitecontainer port 80https://docs.thilke.com
GiteaForge, issues, PRs, CIlocal composehttps://git.thilke.com
MulticaUI and task dashboardlocal composehttps://control.thilke.com

Agent Runtime

The native runtime lives in thilke/agent and replaces the earlier Pi-derived approach with a Rust-first daemon and TUI.

  • crates/thilke-agentd: CLI, HTTP API, run persistence, ADK-Rust integration, issue planning, action execution, Gitea client, jj adapter, GraphRAG lookup, and model config.
  • crates/thilke-tui: Ratatui interface for viewing runs, inspecting proposed actions, and approving or rejecting actions.

Run mirrors persist request, session, events, artifacts, proposed actions, branch recovery, eval, summary, trace, and validation output.

Agent Roles

RolePurposeMultica mapping
PurveyourSoftware architect and option refinementarchitect
DeputeGeneral implementationdefault
AssayourReview validation and acceptancereview
AvisourIssue triage and clarificationtriage
StewardOperations and reliabilityops
BaillifApproved executionexecutor
FactourRelease and packagingrelease

Issue Execution Loop

plan-issue fetches a Gitea issue, gathers repository and graph context, and writes proposed actions without repository writes. Approvals happen through the TUI or HTTP API. execute-approved refuses required, rejected, or unapproved actions and enforces branch, validation, and protected-branch safeguards.

thilke-agentd plan-issue --owner thilke --repo agent --number 1
thilke-agentd execute-approved --repo-dir /home/thilke/src/agent --run-id $RUN_ID

Jujutsu VCS Workflow

Agents use jj as the primary local VCS interface while preserving Git compatibility for Gitea. Initialize colocated jj, use jj new and jj bookmark set for branches, jj describe for commits, jj git export before Git/Gitea operations, and jj git push --bookmark for pushes. Persist jj_change_id and jj_operation_id in recovery manifests.

GraphRAG and Memory

The context service is currently a persistent SQLite-backed graph and memory API with a Pathway-compatible service boundary. It stores repository entities, services, agents, issues, run facts, semantic memory, episodic memory, and procedural playbooks.

Endpoints: POST /v1/admin/refresh, POST /v1/graphrag/search, POST /v1/memory/lookup, and POST /v1/memory/record.

Memgraph GraphRAG, AI Memory, and Agentic AI

Thilke uses Memgraph as the real-time graph backend for three related workloads:

  • GraphRAG: retrieval that combines text relevance with graph expansion and Cypher traversal.
  • AI Memory: semantic, episodic, and procedural memory in one connected graph.
  • Agentic AI: an execution and reasoning graph for tasks, runs, actions, outcomes, and policies.

Pathway remains the ingestion and API service. Memgraph is the graph execution and memory backend. SQLite FTS remains a local fallback/search index.

Services

ServiceEndpointPurpose
thilke-memgraph.servicebolt://127.0.0.1:7687Memgraph database for graph memory, GraphRAG, and reasoning paths
thilke-pathway-context.servicehttp://127.0.0.1:8090Ingestion, HTTP API, dual-write adapter
thilke-iii-worker.servicews://127.0.0.1:49134Exposes graph functions to iii

Memgraph data is persisted under /var/lib/thilke-agent/memgraph and mounted into the container.

Memory model

The adapter writes these node families:

  • (:ThilkeEntity) for repositories, issues, runs, artifacts, and procedures.
  • (:Memory) for all memory records.
  • (:Memory {layer: "semantic"}) for facts, entities, and issue knowledge.
  • (:Memory {layer: "episodic"}) for run history, traces, validations, and outcomes.
  • (:Memory {layer: "procedural"}) for playbooks, policies, and repeatable workflows.

Important relationships:

  • (repo)-[:THILKE_RELATION {kind: "has_issue"}]->(issue)
  • (run)-[:THILKE_RELATION {kind: "has_artifact"}]->(artifact)
  • (memory)-[:ABOUT]->(entity)

API surface

Pathway context endpoints:

curl -fsS http://127.0.0.1:8090/healthz
curl -fsS -X POST http://127.0.0.1:8090/v1/admin/refresh

GraphRAG search:

curl -fsS -H 'content-type: application/json' \
  -d '{"query":"agent memory GraphRAG","limit":8}' \
  http://127.0.0.1:8090/v1/graphrag/search

Memory lookup:

curl -fsS -H 'content-type: application/json' \
  -d '{"query":"jj recovery","layer":"procedural","limit":8}' \
  http://127.0.0.1:8090/v1/memory/lookup

Read-oriented Cypher:

curl -fsS -H 'content-type: application/json' \
  -d '{"query":"MATCH (m:Memory) RETURN count(m) AS memories","limit":5}' \
  http://127.0.0.1:8090/v1/memgraph/cypher

The Cypher endpoint also accepts params for safer automation:

{
  "query": "MATCH (r:ReasoningRun {run_id: $run_id})-[:PROPOSES]->(a:Action) RETURN r.run_id AS run_id, count(a) AS actions",
  "params": {"run_id": "019e53d7-cb42-7272-a077-a4fa901bb73f"},
  "limit": 5
}

Agentic AI reasoning graph

plan-issue mirrors its proposed execution path into Memgraph. This makes the agent plan queryable before any write action is approved, which is the first concrete slice of the Memgraph Agentic AI model.

For each issue planning run, Thilke writes:

  • (:ReasoningRun:AgentRun) with run_id, agent, status, summary, model_provider, model_tier, and recovery branch.
  • (:Task:GiteaIssue) for the source issue.
  • (:Action:ProposedAction) for each gated action, with action_id, kind, risk, risk_score, approval, dry_run, and ordinal.
  • (ReasoningRun)-[:PLANS_FOR]->(Task).
  • (ReasoningRun)-[:PROPOSES {ordinal}]->(Action).
  • (Action)-[:NEXT_ACTION]->(Action) for ordered execution-path traversal.

This lets agents and reviewers ask graph-native questions before writes occur:

curl -fsS -H 'content-type: application/json' \
  -d '{"query":"MATCH (r:ReasoningRun {run_id: $run_id})-[:PROPOSES]->(a:Action) RETURN r.run_id AS run_id, count(a) AS actions","params":{"run_id":"019e53d7-cb42-7272-a077-a4fa901bb73f"},"limit":5}' \
  http://127.0.0.1:8090/v1/memgraph/cypher

The current deployment was dogfooded with issue thilke/agent#1; the resulting graph contained one ReasoningRun, one GiteaIssue task, and five proposed actions connected by PROPOSES and NEXT_ACTION edges.

iii functions

The Thilke iii worker exposes:

  • thilke.graph.search
  • thilke.graph.memory_lookup
  • thilke.graph.cypher

This gives agents a stable capability-bus interface for GraphRAG, AI memory, and reasoning-graph queries without coupling agent code directly to Memgraph.

ADK integration plan

ADK-Rust should talk to memory through a ThilkeMemoryStore adapter:

  1. before planning: call GraphRAG/memory lookup for issue, repo, and agent-role context;
  2. during execution: append episodic events and observations;
  3. after execution: store summary, validation result, PR outcome, cost, model tier, and errors;
  4. during future planning: use graph edges and prior outcomes to score action paths.

The current implementation establishes the backend, APIs, and pre-write reasoning-plan mirror. The next step is to persist post-write outcomes from execute-approved and feed success/failure edges back into future planning.

Validation

systemctl is-active thilke-memgraph thilke-pathway-context
curl -fsS http://127.0.0.1:8090/healthz
curl -fsS -H 'content-type: application/json' \
  -d '{"query":"MATCH (m:Memory) RETURN count(m) AS memories","limit":5}' \
  http://127.0.0.1:8090/v1/memgraph/cypher

Multica Bridge

Multica is a human-facing UI and task/event surface, not the durable source of truth. Gitea owns code, issues, PRs, and reviews. thilke-agentd owns run mirrors. jj plus branch-recovery.json owns VCS recovery. GraphRAG owns context.

The bridge maps Multica events to Thilke roles, triggers safe plan-issue runs from Gitea-linked tasks, syncs summaries back, and skips events without canonical Gitea targets.

iii Capability Bus

Thilke runs iii as the live capability bus for agent-adjacent services. It provides a discoverable worker/function/trigger surface for agents, dashboards, and bridge services while preserving durable sources of truth elsewhere.

Source of truth boundaries

  • thilke-agentd is the durable ADK-Rust run authority.
  • Gitea is authoritative for issues, branches, pull requests, and review status.
  • Jujutsu/Git manifests are authoritative for recoverable code changes.
  • Pathway/SQLite graph memory is authoritative for graph and memory state.
  • Multica is a display and ingress adapter, not the source of truth.
  • iii composes capabilities through named functions and traceable invocations.

Deployed services

ServiceEndpointPurpose
thilke-iii.service127.0.0.1:3111, 127.0.0.1:49134iii engine, HTTP surface, worker websocket
thilke-iii-worker.servicews://127.0.0.1:49134Registers Thilke functions
thilke-multica-bridge.service127.0.0.1:8093Routes eligible Multica events through iii

The engine is installed from thilke/agent and configured at /etc/thilke-agentd/iii-config.yaml.

Durability posture

The engine no longer runs with --use-default-config. It uses source-controlled config with file-backed adapters mounted at /var/lib/thilke-agent/iii.

Current adapters:

  • iii-state: kv, file_based, /data/state_store
  • iii-stream: kv, file_based, /data/stream_store
  • iii-queue: builtin, file_based, /data/queue_store
  • iii-cron: kv, file_based, /data/cron_store
  • iii-observability: memory exporter for local traces, metrics, and logs

Anonymous iii telemetry is disabled with III_TELEMETRY_ENABLED=false. The engine runs with III_ENV=production.

If iii becomes multi-host, replace file-backed adapters with Redis/RabbitMQ per upstream iii guidance.

Registered Thilke functions

  • thilke.agent.health: checks thilke-agentd health.
  • thilke.graph.search: calls Pathway GraphRAG search.
  • thilke.multica.agent_map: exposes Multica-to-Thilke agent role mapping.
  • thilke.agent.plan_issue: runs thilke-agentd plan-issue into durable run mirrors.

Multica event path

sequenceDiagram
    participant M as Multica UI/API
    participant B as thilke-multica-bridge
    participant I as iii engine
    participant W as thilke-iii-worker
    participant A as thilke-agentd
    participant G as Gitea

    M->>B: issue status/update event
    B->>B: resolve role and Gitea target
    B->>I: trigger thilke.agent.plan_issue
    I->>W: invoke function
    W->>A: thilke-agentd plan-issue
    A->>G: read issue context
    A->>A: write durable run mirror and proposed actions
    W-->>I: run result
    I-->>B: processed via iii

The path remains approval-gated. plan-issue creates context and proposed actions but performs no repository writes. Writes require explicit action approval and execute-approved.

Smoke validation

From /home/thilke/src/agent on the host:

scripts/smoke/iii-multica-process-next.sh

Expected output:

bridge_iii_enabled ws://127.0.0.1:49134
III_MULTICA_PROCESS_NEXT_OK <run-id>

Operations

Check services:

systemctl is-active thilke-iii thilke-iii-worker thilke-multica-bridge thilke-agentd

Inspect logs:

docker logs --tail 120 thilke-iii
journalctl -u thilke-iii-worker -n 120 --no-pager

Reinstall from source:

cd /home/thilke/src/agent
scripts/install-iii-services.sh

Deployment

The deployment target is 5.78.191.210. Agent services are systemd units. Public routes use Traefik file-provider and selected Docker services.

Docs build with mdbook build /home/thilke/src/docs, deploy to /var/www/thilke-docs, and are served by thilke-docs nginx on the edge-router network. The route file is /mnt/HC_Volume_105485887/projects/coolify/proxy-external/dynamic/docs-thilke.yml.

Operations

systemctl is-active thilke-agentd thilke-codex-gateway thilke-pathway-context thilke-multica-bridge
curl -fsS http://127.0.0.1:7817/healthz
curl -fsS http://127.0.0.1:8090/healthz
curl -fsS http://127.0.0.1:8093/healthz
curl -fsS https://docs.thilke.com/ | head

Use journalctl -u <service> for systemd logs and docker logs thilke-docs for docs. Use jj op log and jj undo for local operation recovery.

Monitoring and Status

Thilke agent operations use a layered status model:

  1. systemd service health for each local service;
  2. HTTP health endpoints for the daemon, Codex gateway, graph context, and Multica bridge;
  3. iii runtime checks for source-controlled config, telemetry opt-out, and absence of in-memory production warnings;
  4. durable run mirror inspection under /var/lib/thilke-agent/runs;
  5. optional smoke execution through the Multica-to-iii-to-agentd path.

Canonical status command

Run from the agent repository on the host:

cd /home/thilke/src/agent
scripts/thilke-agent-status.py --pretty

The script emits JSON and exits non-zero if any required service or endpoint is unhealthy.

Important fields:

  • ok: aggregate pass/fail.
  • services: systemd is-active results.
  • http: service health endpoint responses.
  • iii.telemetry_disabled: verifies iii anonymous telemetry is disabled.
  • iii.in_memory_warning_present: must be false for the production-like deployment.
  • iii.config_file_active: verifies iii loaded /etc/iii/iii-config.yaml.
  • storage.runs_count: count of durable run mirrors.
  • latest_runs: recent run mirror metadata.

Smoke mode

Use smoke mode when validating a deploy or debugging the Multica event path:

scripts/thilke-agent-status.py --smoke --pretty

Smoke mode calls scripts/smoke/iii-multica-process-next.sh. It creates a durable plan-issue run through:

Multica bridge -> iii -> thilke-iii-worker -> thilke-agentd plan-issue

It remains write-safe. It performs planning only and does not mutate repositories.

Expected smoke marker:

III_MULTICA_PROCESS_NEXT_OK <run-id>

Direct service checks

systemctl is-active \
  thilke-agentd \
  thilke-codex-gateway \
  thilke-pathway-context \
  thilke-multica-bridge \
  thilke-iii \
  thilke-iii-worker
curl -fsS http://127.0.0.1:7817/healthz
curl -fsS http://127.0.0.1:8092/healthz
curl -fsS http://127.0.0.1:8090/healthz
curl -fsS http://127.0.0.1:8093/healthz

Log inspection

docker logs --tail 120 thilke-iii
journalctl -u thilke-iii-worker -n 120 --no-pager
journalctl -u thilke-agentd -n 120 --no-pager
journalctl -u thilke-multica-bridge -n 120 --no-pager

Next monitoring work

  • Export the JSON status through a local authenticated endpoint.
  • Add a scheduled status mirror into Multica for display-only dashboards.
  • Add Prometheus counters for run duration, status, model tier, approval latency, smoke results, and path (iii versus direct fallback).
  • Add iii trace and metric retrieval to the status script once the deployed engine API shape is stable.

Security

Agent APIs bind to loopback by default. Write operations are approval-gated. Tokens live in /etc/thilke-agentd or server-local secret files and must not be committed. Public docs must not contain secrets.

Guardrails: do not print secrets, never push directly to protected branches from an agent, refuse PR creation unless validation artifacts exist, gather read-only context before writes, and treat Multica events as requests rather than trusted commands.

APIs

Agent daemon: GET /healthz, GET /v1/capabilities, GET /v1/runs, GET /v1/tools, GET /v1/runs/{run_id}/actions, POST /v1/runs/{run_id}/actions/{action_id}/approval, GET /v1/runs/{run_id}/branch-recovery.

Context service: GET /healthz, POST /v1/admin/refresh, POST /v1/graphrag/search, POST /v1/memory/lookup, POST /v1/memory/record.

Codex gateway: GET /v1/models, POST /v1/chat/completions. Multica bridge: GET /healthz, GET /v1/agents/map, POST /v1/sync/agent-to-multica, POST /v1/ingress/multica-issue, GET /v1/events/pending, POST /v1/events/process-next.

Roadmap

Near term: expand execute-approved, surface GraphRAG citations in the TUI, add remote authenticated daemon access, make Multica sync more useful without making it authoritative, and add docs/route CI.

Medium term: use real Pathway streaming where useful, add Langfuse or equivalent traces, add agent evals for laziness and validation quality, and add a GPUI dashboard.

Long term: build the self-editing game/engine loop where code, logic, and low-poly asset agents coordinate through the same durable execution graph.

Appendix: Current State

Current host paths: /home/thilke/src/agent, /home/thilke/src/docs, /home/thilke/src/platform, /etc/thilke-agentd, /var/lib/thilke-agent, /var/www/thilke-docs, and /mnt/HC_Volume_105485887/projects/coolify/proxy-external/dynamic. Installed services include thilke-agentd, thilke-codex-gateway, thilke-pathway-context, and thilke-multica-bridge. jj 0.41.0 is installed and expected for agent VCS.