8000 GitHub - boucaron/ACTA_Gamma: ACTA Gamma: a small stateless runner that treats LLMs as controlled actions — one prompt, one recorded, auditable result. Versioned skills, immutable contexts, replayable runs. · GitHub
[go: up one dir, main page]

Skip to content

About

ACTA Gamma: a small stateless runner that treats LLMs as controlled actions — one prompt, one recorded, auditable result. Versioned skills, immutable contexts, replayable runs.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

933 Commits

Folders and files

Repository files navigation

ACTA Gamma

ACTA Gamma logo

LLMs as actions, not agents.

ACTA Gamma is a small runner for executing one controlled LLM action at a time and recording the outcome.

You provide:

  • a model — where the LLM runs
  • a skill — a versioned prompt describing the action
  • a context — an immutable snapshot of input data

ACTA Gamma combines them into an execution, makes one LLM call, and records the result and execution history in SQLite.

You decide what happens next. ACTA Gamma makes one LLM call and records what happened.

This is deliberately not an agent framework.

The project is currently an early prototype / POC. See docs/status.md.


Why ACTA Gamma?

LLMs are often embedded in increasingly autonomous systems: agents, tools, planners, memory, queues and workflows.

ACTA Gamma takes the opposite approach.

It treats an LLM as a deterministic-flow component:

Context + Skill + Model
          │
          ▼
      One LLM call
          │
          ▼
       Result
          │
          ▼
    Audit trail

The surrounding application decides what happens before and after the call.

This makes ACTA Gamma useful for tasks such as:

  • classification
  • extraction
  • review
  • analysis
  • transformation
  • auditing
  • document processing
  • other repeatable LLM operations

Core concepts

Model

A registered LLM endpoint and model identifier.

ACTA Gamma speaks two backend dialects, declared by the model's backend value:

  • llamacpp — a local llama.cpp llama-server router serving GGUF models (the default path, described below)
  • openai — any strict OpenAI-compatible HTTP server (Strata, vLLM, …)

The dialect decides the HTTP shapes the runner uses (catalog call, context ceiling field, response_format envelope). It is a closed vocabulary: only llamacpp and openai are accepted.

Skill

A versioned prompt template describing the action to perform.

A skill may also define an output schema for structural validation.

Context

An immutable snapshot of input data.

The context is the user message sent to the model. Once created, it can be reused by multiple executions.

Revision

Skills and models are versioned.

Editing one creates a new immutable revision rather than changing the revision already used by an execution.

Execution

An execution binds:

Context + Skill revision + Model revision

and records the resulting LLM call.

Executions move through states such as:

pending → running → completed
                  ↘ failed
                  ↘ cancelled

cancelled comes from acta_cli exec cancel or the GUI Cancel button; a failed execution goes back to pending through exec reset.

They can be replayed by creating another execution with the same inputs.

Replay provides input determinism, not output determinism: the same request inputs do not guarantee identical model output.


What ACTA Gamma does — and does not

Does Does not
Run one-shot LLM actions Act as an autonomous agent
Version skills and models Maintain conversational state
Keep immutable input snapshots Delegate or orchestrate work
Record results and execution logs Provide automatic retries
Replay executions Provide streaming responses
Support multiple local models Manage the model server
Provide CLI and GUI interfaces Provide users, permissions or queues
Store everything in SQLite Require a database server

For the design rationale and non-goals, see docs/PointOfView.md.


Quick start

1. Build

The C targets build with plain make on Windows (MinGW/MSYS2), Linux (gcc/clang) and macOS (Xcode clang); the Qt 6 GUI additionally needs qmake6. Install the required dependencies for your platform, then:

make all

Run the test suites with:

make test

The optional Qt GUI is built separately:

make gui

See docs/building.md for platform-specific dependencies and build instructions.


2. Start llama.cpp

ACTA Gamma's default path is llama-server in router mode — register such a model with "backend": "llamacpp". A strict OpenAI-compatible server ("backend": "openai") works the same way, see OpenAI-compatible backends below.

For example:

llama-server --models-dir models -c 2048

Place your GGUF models in models/.

The server is expected at:

http://127.0.0.1:8080

A small example model can be downloaded with:

hf download \
  Qwen/Qwen2.5-0.5B-Instruct-GGUF \
  --include "*q4_k_m.gguf" \
  --local-dir models/

In router mode each served model's id is the basename of its GGUF file, so the file above is registered as qwen2.5-0.5b-instruct-q4_k_m — that is the value model_identifier must carry (see docs/llamacpp_server_contract.md §1).

The -c value is the backend's token context window; adjust it for your model.

See docs/llamacpp_server_contract.md for the backend contract.

Minimal example

Initialize a new database:

acta_cli db init

Register a model:

acta_cli model create --json \
'{
  "name": "llama-local",
  "backend": "llamacpp",
  "base_url": "http://127.0.0.1:8080",
  "model_identifier": "qwen2.5-0.5b-instruct-q4_k_m"
}'

Create a skill:

acta_cli skill create \
  --name sentiment \
  --prompt_template 'Classify the sentiment of the input. Reply with JSON only.' \
  --output_schema '{"type":"object","required":["label","confidence"],"properties":{"label":{"type":"string"},"confidence":{"type":"number"}}}'

output_schema is stored as text, so it must arrive as a string containing JSON — passing a JSON object inside --json stores null (the schema is silently dropped). See docs/cli_spec.md.

Create an immutable context:

acta_cli context create --json \
'{
  "type": "text",
  "content": "The build system shipped on time and the release went smoothly."
}'

Create an execution:

acta_cli exec create --json \
'{
  "context_id": 1,
  "skill_revision_id": 1,
  "model_revision_id": 1
}'

The runner needs an API key before it will start. Export OPENAI_API_KEY — set it to "" for a keyless local llama-server. If the variable is unset and the config file has no "api_key", run refuses to start (exit 4) before claiming anything. See Configuration.

Optionally check the backend without making an LLM call:

acta_runner check 1        # 1 = the MODEL record id, not an execution id

Run the execution:

acta_runner run 1

Inspect the result:

acta_cli exec get 1
acta_cli log list 1

The complete CLI contract and all available options are documented in docs/cli_spec.md.


OpenAI-compatible backends

A model registered "backend": "openai" is served by any strict OpenAI-compatible HTTP server — Strata, vLLM, … The name describes the HTTP dialect, not a vendor.

acta_cli model create --json \
'{
  "name": "strata-local",
  "backend": "openai",
  "base_url": "http://127.0.0.1:8080",
  "model_identifier": "qwen3.8-flash-next-iq3_xxs"
}'

Everything after that is identical — same exec create, same acta_runner run 1. What differs is what the runner puts on the wire:

Concern llamacpp openai
context ceiling entry max_context entry meta.n_ctx
model catalog audit GET / not requested ("catalog": null)
top_k sent omitted
response_format {"type":"json_schema","schema":{…}} {"type":"json_schema","json_schema":{"name":"acta_output","strict":true,"schema":{…}}}

The dialect comes from the model revision, so the same execution row and revision always produce the same request. acta_runner check --base-url … --model-identifier … [--dialect llamacpp|openai] probes a server before anything is registered; acta_runner run <id> --dialect … is a logged override — it never edits the model row, and the execution log records that an override happened.

See docs/openai_dialect_contract.md.


What gets recorded?

An execution records the important parts of the operation:

context
skill revision
model revision
status
timestamps
raw response
validated result
error, if any
execution log

The execution log records the major phases of the run, making it possible to inspect what happened rather than only seeing the final answer.

For example:

execution_started
context_loaded
prompt_resolved
preflight_passed
llm_request
llm_response
execution_completed

The exact execution and logging contract is documented in docs/runner_contract.md.


Revisions and replay

Skills and models are versioned.

An execution never points at a mutable skill or model directly. It points at a specific revision.

That means an old execution remains tied to the exact skill/model definitions it originally used.

A replay can reuse:

same context
same skill revision
same model revision

and therefore reproduce the same request inputs.

This is useful for auditing, comparison and experimentation.

See:


CLI

The main commands are:

Command Purpose
acta_cli db init Initialize a database
acta_cli db migrate Apply database migrations
acta_cli db backup --to <path> Create an atomic database snapshot
acta_cli model create Register a model
acta_cli skill create Create a versioned skill
acta_cli context create Create an immutable context
acta_cli exec create Create an execution
acta_runner check <model-record-id> Check backend/model availability
acta_runner run <id> Execute one run
acta_runner run --pending [--max N] Run pending executions (capped)
acta_cli model/skill update Revise → new immutable revision
acta_cli exec cancel <id> Cancel a pending/running execution
acta_cli db version Report the SQLite version
acta_cli exec reset <id> Reset a failed execution
acta_runner sweep --stale-seconds N Recover stale executions
acta_cli exec get <id> Inspect an execution
acta_cli log list <id> Inspect its execution log

The two CLI binaries (acta_cli, acta_runner) support:

--help
--version

For the complete command syntax, JSON format, flags and error contracts, see docs/cli_spec.md.


GUI

The optional Qt 6 GUI provides a convenient interface for human users.

It covers the same core workflow:

Model
  ↓
Skill
  ↓
Context
  ↓
Execution
  ↓
Run
  ↓
Result + Log

The GUI is intended as a convenience layer. Scripted and programmatic use should use acta_cli and acta_runner.

The Run button is not a shell-out to acta_runner: the GUI executes the same pipeline in-process on a worker thread, compiling the runner's own source files (run.c, backend.c, dialect.c, argparse.c, deathmark.c) — one pipeline codebase, no second copy — on its own database connection. While a run is in flight the button toggles to Cancel (the row becomes cancelled), and a failed row can be retried with Retry (failed → pending, the same transition as acta_cli exec reset). See docs/building.md, "GUI–runner source coupling".

Build it with:

make gui

See docs/building.md for GUI build requirements.


Architecture

ACTA Gamma is intentionally small:

                    ┌─────────────────┐
                    │     acta_gui    │
                    │     Qt 6        │
                    └────────┬────────┘
                             │
                    ┌────────▼────────┐
                    │    acta_runner   │
                    │   one LLM call   │
                    └────────┬────────┘
                             │
                    OpenAI-compatible
                         HTTP API
                             │
                    ┌────────▼────────┐
                    │   llama-server  │
                    │     llama.cpp   │
                    └─────────────────┘

                    ┌─────────────────┐
                    │     acta_cli    │
                    └────────┬────────┘
                             │
                    ┌────────▼────────┐
                    │     acta_db     │
                    │     SQLite      │
                    └─────────────────┘

The main components are:

Component Role
acta_db/ SQLite persistence library
acta_cli/ Command-line interface
acta_runner/ LLM execution pipeline
acta_gui/ Optional Qt desktop interface

See docs/DBDesign.md and docs/runner_contract.md for the detailed component contracts.

Over that HTTP API the runner speaks two dialects: llamacpp (the llama-server above) and openai (any strict OpenAI-compatible server) — see OpenAI-compatible backends.


Configuration

The most important configuration options are:

OPENAI_API_KEY

API key used for backend HTTP calls.

For a keyless local llama-server, an empty value is valid:

export OPENAI_API_KEY=""

ACTA_DB

Optional database path override.

ACTA_Gamma.conf

Optional per-machine configuration file.

It can contain settings such as:

{
  "api_key": "...",
  "db": "...",
  "max_chars": 100000,
  "timeout": 600
}

Configuration precedence and security rules are documented in docs/runner_contract.md and docs/cli_spec.md.


Important limitations

ACTA Gamma is intentionally narrow.

In particular:

  • it does not protect against prompt injection
  • output-schema validation checks structure, not semantic correctness
  • it does not automatically retry failed executions
  • it does not stream model responses
  • it does not manage the llama.cpp server
  • the backend dialect is a declared, closed two-value vocabulary (llamacpp / openai) on the 7669 model revision — there is no plugin mechanism and no runtime dialect detection
  • the SQLite design is intended for a private local database, not a multi-user server: one connection per binary, single-writer by design, with a 5 s busy_timeout absorbing transient contention and a wrapped SQLITE_BUSY diagnostic when the wait fails (docs/DBDesign.md)

The context is passed to the model as input; applications handling untrusted data are responsible for deciding how that data should be treated.

These are design constraints rather than hidden features. See docs/PointOfView.md and docs/status.md.


Documentation

The README intentionally stays high-level. The detailed contracts live here:

Document Contents
docs/building.md Dependencies and platform-specific builds
docs/cli_spec.md CLI commands, flags, JSON and errors
docs/runner_contract.md Execution pipeline and runner behavior
docs/DBDesign.md SQLite schema, revisions, lifecycle and migrations
docs/llamacpp_server_contract.md llama.cpp backend contract
docs/openai_dialect_contract.md OpenAI-compatible (openai dialect) contract
docs/PointOfView.md Design philosophy and non-goals
docs/status.md Current project status and product decisions
docs/known_issues.md Known issues
docs/examples/ Worked examples and tutorials
docs/examples/README.md The four tutorials in order + the shared working-copy convention
docs/archive/ Completed plans and session records (no open work)
docs/archive/backend_dialects.md The dialect matrix (§2), where the dialect comes from (§3.2), the four decisions (§9)

Current status

Early prototype / POC.

The core pipeline is implemented:

  • SQLite persistence
  • versioned skills and models
  • immutable contexts
  • execution lifecycle
  • execution logging
  • standalone runner
  • CLI
  • optional Qt GUI
  • replay
  • soft delete / restore
  • stale execution recovery
  • schema migrations (db migrate)
  • backend health check (acta_runner check) — no completion tokens, no DB writes
  • auto preflight before a run is claimed
  • death marker for clean process exits mid-run
  • database backup
  • two backend dialects (llamacpp / openai) carried by the model revision
  • live backend checks (make test-live*), never part of make test
  • per-machine config file (ACTA_Gamma.conf)
  • 5 s busy_timeout over a single-writer SQLite file
  • in-app Run / Cancel / Retry in the GUI

The project is still at an early productization stage.

See docs/status.md for the current status and deliberate product decisions.


License

BSD Zero Clause License (BSD-0-Clause) — the full text is in LICENSE, which also carries SPDX-License-Identifier: 0BSD so license tooling reports the same license the README names.


Third-party code

ACTA Gamma uses:

  • cJSON — MIT
  • libcurl — curl license
  • a public-domain SHA-256 implementation derived from Brad Conte's crypto-algorithms

See docs/building.md and the source tree for details.

About

ACTA Gamma: a small stateless runner that treats LLMs as controlled actions — one prompt, one recorded, auditable result. Versioned skills, immutable contexts, replayable runs.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

0