Help us shape the future of Go! Take the 2026 Go Developer Survey

questlock

module
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 14, 2026 License: MIT

README

Coordinate shared agent work before paying for it again.

CI

Run the demo · Download · Container · Fork Questlock · Contribute

Ask a question · Security · Architecture

An agent stalls. Another takes over and finishes. The original wakes up with a confident, outdated write. Questlock checks its expected version before accepting the update. An exact retry of a successful publish recovers its original receipt.

An experimental Go + SQLite broker for cooperating agents. It controls publication of shared text artifacts; it does not run or sandbox the agents.

The quest theme is a little weekend motivation. Underneath it: a compiled Go broker, a Go client library, SQLite transactions, and concrete failure tests. One host. No Kubernetes. Offline demos need no model account.

Reduce repeated model work

Two workers ask for the same approved handoff. One model call should be enough. Questlock now offers a Go inference library and a bounded model-task CLI for OpenAI Responses, Anthropic Claude Messages, and local Ollama models. The worker plans whole context chunks, checks token and configured cost allowances, claims the task in shared storage, and saves the completed answer for explicitly opted-in reuse.

./bin/questlock model quest
./bin/questlock model plan --spec examples/model-workflows/openai-handoff.json
./bin/questlock model install --agents codex,claude

The model quest runs three simple and three complex scenarios offline, with real authenticated HTTP/SQLite coordination and deterministic model fixtures. It demonstrates 20 simultaneous workers starting one generation, reuse after a broker restart, context reduction, preflight rejection, and an unknown outcome retaining its budget reservation. No API key or paid call is needed for this demo.

Local models without provider token bills · What, why, and how · Setup, Codex/Claude skills, and model specs

Local Ollama generation needs installed local weights and no provider API key. Cloud generation needs the selected provider's API key. Reuse can avoid a complete repeated generation; provider prompt caching can reduce eligible input cost. These controls apply to tasks routed through Questlock. They do not train the model, replace an entire Codex/Claude session, or remove provider credit limits. The architecture guide describes OpenRouter composition and states the storage, count-estimate, price, and billing limits. Live local measurements now show exact reuse and quality failures; see the actual evidence. These are not invoice savings or a model ranking.

Delegate, measure, and check the result

v0.3.0 adds a bounded local worker for Codex and Claude, optional metadata observability for Langfuse, and a six-case evaluation command. You declare the task snapshot, resource limits, and deterministic acceptance checks. Only a confirmed passing tier exposes an approved answer. One explicitly configured next tier may run after a known quality failure; uncertain calls stop.

./bin/questlock model evaluate                 # offline fixtures, including failures
./bin/questlock worker run --request approved-task.json --broker http://127.0.0.1:8080
./bin/questlock worker serve --workspace "$HOME/questlock-workspace"

The worker needs a scoped broker credential and installed local weights. Its MCP interface reads only the named approved request file and admits one active task. It makes bounded delegation available to an agent; it does not reroute a whole hosted chat. These usage counters cover the delegated generation and exclude the surrounding hosted assistant's prompt, tool, and context tokens. Langfuse export is opt-in and carries model metadata, usage, timing, outcome, and declared check scores without prompts or answer text.

Streaming Ollama jobs measure client-observed first content and output intervals. Each invocation has separate phase timings; an exact reuse reports zero new usage and no new generation timing. These distinguish faster retrieval from faster inference, and explicit price estimates from provider invoices.

Our first real local run rejected both configurations. The six-case suite passed 4/6 checks with one cap and 3/6 with another. All 12 exact repeats avoided new generation, but reuse preserved the wrong answers too. The evaluator selected neither configuration, and a failing worker withheld its answer. This is why quality checks accompany cost measurements.

A separate bounded MCP ticket extraction passed strict JSON and exact-value checks with 58 input / 21 output tokens; its exact repeat made no new generation. The self-hosted Langfuse CI contract also passed actual metadata readback. See the measurement record for timings, scope, and limits.

Delegation and MCP setup · Langfuse, timings, and evaluation · Actual local measurements and limits

Count the work a person actually accepts

A check-passing answer can still need a rewrite. The v0.4.0 experimental source candidate adds explicit human outcome feedback, separate from worker checks. Opted-in invocations record content-free attempt metadata in the existing scoped broker. A reviewer can accept, rewrite, reject, or reopen the work; every rewrite clears acceptance until the reviewer explicitly accepts the final artifact again.

./bin/questlock outcome quest                  # six synthetic offline scenarios

The cohort report counts all recorded attempts, including failed and rejected work, alongside explicit reviewer time and an hourly rate. Cost per currently accepted outcome stays unknown when required accounting is missing, and is undefined with no accepted outcomes. These are configured estimates for recorded work, not invoices or whole-chat costs. No editor watching, automatic acceptance, model training, or human-feedback export is implied.

What, why, and how human feedback works · Synthetic examples · Editable feedback diagram

A companion layer for the OpenRouter ecosystem

OpenRouter is a strong common interface for models, routing, and provider caching. Its response cache already makes identical completed requests reusable. OpenRouter routes the model. Questlock coordinates the work. OpenRouter is the switchboard. Questlock helps keep a swarm from running up duplicate tabs.

Questlock's intended add-on role is bounded context, shared task admission, durable results, and budget coordination around the provider-routing layer. A supported OpenRouter adapter remains future work; this release runs the direct OpenAI, Claude, and local Ollama adapters described above. Add-on architecture and sources · Positioning and reproducible evidence

Start the quest

macOS or Linux: install and run in four commands. No Go or model account needed.

git clone https://github.com/spfuzzylink/questlock.git
cd questlock
./scripts/install.sh
./bin/questlock quest

The installer selects your OS/CPU, verifies the release checksum, and puts one executable in bin/. It needs curl, tar, and sha256sum or shasum; it uses no sudo and changes no shell settings. The demo cleans up its temporary state.

Download without Git · Installation, requirements, and updates

Download a binary

The current experimental release is v0.3.0. Choose your operating system and CPU; x86-64 covers 64-bit Intel and AMD processors. No Go installation is needed.

System ARM64 x86-64 (Intel / AMD)
macOS 13+ Download Download
Linux Download Download

Compare the archive's SHA-256 with checksums.txt before extracting, then run ./questlock quest. The installer above performs the checksum check for you. Release notes. Older releases, including v0.2.0, remain available.

Try the container

The public GitHub Packages image supports Linux ARM64 and x86-64. With Podman running:

podman run --rm --network none --read-only \
  --cap-drop all --security-opt no-new-privileges \
  --memory 256m --cpus 1 --pids-limit 128 \
  --tmpfs /data:rw,nosuid,nodev,noexec,size=64m,mode=1777 \
  ghcr.io/spfuzzylink/questlock:v0.3.0 quest

Use docker in place of podman if preferred. The image pulls without a registry login; the demo then runs with networking disabled and no host folders or ports shared. Container usage, persistent deployment, and updates.

Explore the failure case

Developing the source? Install Go 1.26+ and run make quest instead. The installer downloads the version in VERSION; a source build runs your checkout. make check also needs Python 3 and a C toolchain for Go's race detector.

Quest 001: keep a stale worker from rewriting the present.

The executable launches real broker and worker subprocesses in temporary state. It kills a worker after it saves its intended write, lets another publish, resumes the stale request, then hard-kills and restarts the broker.

PASS  Created shared artifact at version 1
PASS  Killed worker A after it saved a write based on version 1
PASS  Worker B published version 2
PASS  Restarted worker A; its stale publish was rejected with HTTP 409
PASS  Hard-killed and restarted broker; version 2 survived
PASS  Retried the acknowledged operation; original result returned without version 3
PASS  Durable journal contains 2 accepted, 1 rejected, and 1 replayed publish

These are deterministic test workers, not a live LLM swarm. The quest runs through the same HTTP API and storage engine used by real clients. Temporary state is removed when it finishes, including its generated fixture credentials.

What is implemented

Quest Status Concrete behavior
Guard the gate Implemented A credential grants access to one shared scope.
Reject the stale challenger Implemented Compare-and-swap rejects outdated writes with HTTP 409.
Recover the lost reply Implemented An exact retry recovers the original successful result.
Survive the restart Tested Acknowledged data and receipts survive broker process kills.
Leave a trace Implemented Accepted, conflicting, and replayed publishes enter a durable journal.
Open a second gate Future experiment Multi-host coordination, placement, and failure recovery.

The guarantee is deliberately narrow: a publish is accepted only when its expected version matches. Artifact content, its current pointer, the successful retry receipt, and the journal entry commit in the same SQLite transaction.

Where it fits

Use it for shared agent notes, competing text-artifact updates, recovering a publish after a lost response, or separating small experiments into scopes. It also provides runnable ways to study stale workers, broker crashes, and shared model-task coordination on one machine. The model workflow supplies a CLI/Go integration for bounded text tasks; other agent integrations and conflict resolution remain application responsibilities.

See who this could help and why for research, support automation, evaluation, and platform workflows. The notes cover the potential benefit, integration work, pilot checks, and technical limits.

Run your own local broker

After installing (or running make build), start a persistent broker:

umask 077
mkdir -p .questlock
(set -C; ./bin/questlock token create --agent writer-a --scope weekend > .questlock/writer-a.token)
(set -C; ./bin/questlock token create --agent writer-b --scope weekend > .questlock/writer-b.token)
./bin/questlock serve

The default address is 127.0.0.1:8080; state lives in .questlock/state.db. Create each agent once. Restarting with the same database preserves credentials, artifact versions, successful operation receipts, and the journal.

To try the Go client example, install Go and open another terminal in this repository:

export QUESTLOCK_TOKEN="$(cat .questlock/writer-a.token)"
go run ./examples/publish
unset QUESTLOCK_TOKEN

The compilable client example reads the current version, publishes, and retries the exact request. For crash recovery, a worker must save its intended request in its own private scratch space before publishing. On a timeout, reuse that request and operation ID. On a conflict, re-read and reconcile instead of blindly advancing the expected version.

Revoke an agent through the trusted local operator CLI:

./bin/questlock token revoke --agent writer-a

Revoked agent names cannot be reused. Give a replacement credential a new agent name so old audit records and retry receipts keep their original meaning.

Security and your machine

Questlock is designed to keep this experiment's access small and explicit:

  • Local by default. The server binds to literal loopback. Any other bind requires --allow-remote-http. The Podman recipe uses that flag inside the container and publishes only 127.0.0.1 on the host.
  • Credentials stay on the intended connection. The Go client accepts plaintext HTTP only for literal loopback IPs; other endpoints require HTTPS. It rejects redirects and ignores environment proxy settings for its authenticated traffic.
  • One scope per credential. The server chooses the scope from a random token, stores only its SHA-256 digest, and rechecks revocation inside the write transaction.
  • No host-file access API. Artifact keys are logical names stored in SQLite. There is no shell execution, filesystem browsing, model call, or telemetry in the broker. Explicit model CLI workers call providers with their own API keys. The demo's child processes receive a small explicit environment, excluding the parent shell's cloud/API credentials.
  • Private state and bounded input. New state directories use 0700; database files use 0600. Artifact text is capped at 1 MiB, requests and responses are bounded, and the service applies HTTP timeouts.
  • Separate the worker from the vault. Only the broker and trusted operator provisioning containers receive its persistent volume. Never give an agent the database, host secrets, container-engine socket, or the broker's OS credentials.
  • Keep private files out of releases. Git ignores state, tokens, environment files, logs, keys, and binaries. Container builds copy an explicit source allowlist. A tracked-source/history guard runs in CI. Publication also receives a dedicated secret scan; scanners reduce risk but cannot prove the absence of every secret.

This is not an agent execution sandbox or a complete safety system. A permitted worker can deliberately fetch the current version and publish bad content. CAS does not validate reasoning, establish task ownership, or fence external tool effects. Configure worker OS/network isolation separately. The trusted host operator can read and change the database.

Read the security model and reporting guidance before exposing it beyond a local experiment. Never post credentials, private databases, or sensitive artifact content in issues or logs.

Project map

questlock/
  cmd/questlock/       CLI and real process-failure quest
  client/             Public Go client library
  inference/          Context planning, provider adapters, shared claims/budgets
  delegation/         Explicit local-first policy and deterministic quality gates
  evaluation/         Six-case comparisons with fresh/reuse measurements
  observability/      Optional content-free Langfuse OTLP metadata and scores
  worker/             Bounded MCP stdio tool for approved request files
  protocol/           Shared JSON types
  internal/httpapi/   Authenticated HTTP boundary
  internal/store/     SQLite transactions, scopes, versions, receipts
  examples/publish/   Minimal compilable integration
  deploy/quadlet/     Rootless Linux service definition
  docs/               Architecture, API, deployment, validation
  scripts/            Installer, release packaging, public-source guard
  assets/             Repository artwork

Architecture · HTTP API · Deployment · Verification record

make check
make quest
./bin/questlock model quest

The tests cover competing writer processes, scope isolation, revocation, atomic rollback, missing/malformed content, lost responses, replay after newer versions, and worker/broker crashes. Linux deployment has also been exercised with rootless Podman and systemd/Quadlet; see the verification record for versions and limits.

SQLite serializes writes. This prototype has no fleet scheduler, replication, quotas, automatic retention, or demonstrated multi-host scale. Versions and audit history grow over time. Process-crash tests do not establish power-loss durability.

Bring your own failure case

Run the quest, then fork Questlock to explore a failure case or add a small integration example. Reproducible bugs, missing concurrency or recovery tests, and clearer installation notes are useful contributions. Start here, or open an issue with what you tried and what happened. Discuss larger changes before starting them.

Community discussion: r/coolgithubprojects.

Credit and license

Questlock was created and is maintained by @spfuzzylink, with community contributions. Questlock's own code is MIT licensed. Bundled dependencies retain their original terms; third-party notices ship with the archives and container image.

Attribution separates required license notices from optional visible credit. Brand guidance explains how to identify upstream Questlock and independent forks or services. Built out of curiosity, one quest at a time.

Directories

Path Synopsis
Package client provides a bounded, authenticated HTTP client for Questlock.
Package client provides a bounded, authenticated HTTP client for Questlock.
cmd
questlock command
Questlock is a small, durable publishing gate for cooperating agent workers.
Questlock is a small, durable publishing gate for cooperating agent workers.
Package delegation runs an explicit bounded local-first task policy.
Package delegation runs an explicit bounded local-first task policy.
Package evaluation compares explicit inference configurations against bounded, deterministic task checks.
Package evaluation compares explicit inference configurations against bounded, deterministic task checks.
examples
publish command
Run against a local broker: QUESTLOCK_TOKEN=...
Run against a local broker: QUESTLOCK_TOKEN=...
Package inference runs bounded, reusable text-generation jobs through Questlock.
Package inference runs bounded, reusable text-generation jobs through Questlock.
internal
agentsetup
Package agentsetup installs the running Questlock executable and embedded workflow skills.
Package agentsetup installs the running Questlock executable and embedded workflow skills.
httpapi
Package httpapi exposes the storage service through a small authenticated JSON API.
Package httpapi exposes the storage service through a small authenticated JSON API.
store
Package store provides the single-host storage and authorization boundary.
Package store provides the single-host storage and authorization boundary.
Package observability exports bounded execution metadata.
Package observability exports bounded execution metadata.
Package outcomes records human acceptance separately from deterministic inference checks.
Package outcomes records human acceptance separately from deterministic inference checks.
Package protocol defines the JSON contract between Questlock and its clients.
Package protocol defines the JSON contract between Questlock and its clients.
scripts
langfuse-smoke command
Command langfuse-smoke validates the exporter against a disposable Langfuse v4 server.
Command langfuse-smoke validates the exporter against a disposable Langfuse v4 server.
Package worker exposes bounded explicit delegation through MCP over stdio.
Package worker exposes bounded explicit delegation through MCP over stdio.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL