Skip to content
AVIDS2Public

About

No description, website, or topics provided.

Resources

Stars

21 stars

Watchers

0 watching

Forks

Latest commit

 

History

22 Commits

Folders and files

Repository files navigation

vek

vek

Git semantics for AI agent tool calls

PyPI CI Python 3.10+ MIT


Every tool call an agent makes — its input, output, parent, timestamp — is stored as an immutable, content-addressed blob in a local SQLite database. The result is a traceable, forkable, branchable execution DAG you can query, verify, and replay. Zero external dependencies. Framework-agnostic. One function call to integrate.

Why vek?

  • You can't debug what you can't see. Agents make thousands of tool calls. Without a record, you're flying blind.
  • Git proved the model. Content-addressed, immutable, branchable — the same primitives that make code reviewable make agent execution reviewable.
  • Local-first, zero config. .vek/ in your project directory. No server, no API key, no setup.

Install

pip install vek

Quick Start

import vek

# 1. Initialise (once per project)
vek.init()

# 2. Record tool calls
h = vek.store(tool="search", input={"q": "climate"}, output={"results": [...]})

# 3. Inspect
node = vek.show(h)          # full node details
vek.log()                   # execution history
vek.status()                # branch, tip, stats

# 4. Branch & fork (like git)
vek.branch("experiment")    # create/switch branch
vek.fork(h, "alt-path")     # fork at a node

# 5. Verify & re-execute
results = vek.verify(h, executor=my_executor)   # dry-run comparison
new = vek.reexec(h, executor=my_executor)       # re-execute into new ref
vek.checkpoint(h, "v1-verified")                # mark verified position

Auto-recording

# Decorator — wraps any function
@vek.wrap
def search(query: str) -> dict:
    return call_api(query)

# Session — batch recording, atomic
with vek.session() as s:
    s.store(tool="search", input=query, output=results)
    s.store(tool="summarise", input=text, output=summary)

# Hook — intercept a dispatch function
dispatch = vek.hook(original_dispatch)

The Three Pillars

Pillar What API
Store Record every tool call immutably store, session, wrap, hook
Query Search, inspect, verify history query, search, annotate, verify, diff_chains
Re-execute Replay & checkpoint verified chains reexec, checkpoint, list_checkpoints

CLI Reference

vek init                  # create .vek/ repository
vek status                # current branch, tip, stats
vek log [-n 20] [--graph] # execution history / ASCII DAG
vek show <hash>           # inspect a node (short hash OK)
vek cat-file <hash>       # dump raw object content
vek branch [name]         # list or create/switch branches
vek fork <hash>           # fork at a node
vek merge <branch>        # merge branch into current
vek diff <hash1> <hash2>  # structural JSON diff
vek replay <hash>         # replay first-parent chain
vek query [--tool X] [--since T] [--until T] [--branch B] [--limit N]
vek search <pattern> [--field input|output|both] [--limit N]
vek annotate <hash>       # annotate chain with materialised content
vek verify <hash> [--exec-function module:func]  # verify by re-execution
vek diff-chains <h1> <h2> # compare two chains node-by-node
vek reexec <hash> [--exec-function module:func] [--ref name]  # re-execute into new ref
vek checkpoint [label] [hash]  # list or create checkpoints
vek tag [name] [hash]     # list or create tags
vek fsck                  # verify repository integrity
vek gc [--dry-run]        # remove unreachable objects
vek export [--format json|jsonl] [--branch name]
vek import <file> [--format auto|json|jsonl]
vek --version

Python API

Function Description
vek.init() Initialise .vek/ repository
vek.store(tool, input, output) Record one tool call
vek.session() Context manager for atomic batch recording
vek.async_session() Async context manager
vek.wrap(fn) Decorator for auto-recording
vek.hook(dispatch_fn) Wrap a dispatch function
vek.log(n=20) Recent execution history
vek.log_graph() ASCII DAG visualisation
vek.show(hash) Node details with materialised content
vek.cat_file(hash) Raw object bytes
vek.status() Repository summary
vek.branch(name) Create/switch branch
vek.fork(hash, name) Fork at a node
vek.merge(branch) Merge branch (creates multi-parent node)
vek.diff(h1, h2) Structural JSON diff
vek.replay(hash) First-parent chain from root to hash
vek.query(tool=, since=, until=, branch=, limit=) Filtered node query
vek.search(pattern, in_field=, limit=) Search by input/output content
vek.annotate(hash) Annotate chain with materialised content
vek.verify(hash, executor) Dry-run re-execution with output comparison
vek.diff_chains(h1, h2) Compare two chains node-by-node
vek.reexec(hash, executor, ref=) Re-execute chain into new ref
vek.checkpoint(hash, label) Mark verified checkpoint
vek.list_checkpoints() List all checkpoints
vek.tag(name, hash) Lightweight tags
vek.fsck() Integrity verification
vek.gc() Garbage collection
vek.export() Export chains (JSON/JSONL)
vek.import_data(data) Import chains

All hash arguments accept short prefixes (e.g. h[:8]).

Storage Layout

.vek/
├── objects/     # content-addressed hash objects
├── refs/        # branch pointer files
├── HEAD         # current branch
├── config       # repository configuration
└── vek.db       # SQLite — objects + nodes + refs

Data Model

objects:  hash | content
nodes:    hash | tool | input_hash | output_hash | parent_hash | timestamp | merge_parent
refs:     name | hash   (branches, tags with "tag/" prefix, checkpoints with "checkpoint/" prefix)

Object Hashing (git-style)

SHA-256( "blob" + " " + size + "\0" + content )   # input/output blobs
SHA-256( "node" + " " + size + "\0" + content )   # execution nodes

Same content stored exactly once. Different types with identical content produce different hashes.

Merge Nodes

Merge creates a node with two parents: parent_hash (current branch) and merge_parent (target branch). Tool is __merge__.

Concurrency & Safety

  • SQLite WAL mode with 5s busy timeout
  • store() uses BEGIN IMMEDIATE to serialise concurrent ref updates
  • Advisory file lock (HEAD.lock) prevents concurrent branch pointer writes
  • Sessions batch all writes in a single transaction (atomic commit/rollback)
  • verify() and reexec() suppress executor side-effects via ContextVar — executor cannot mutate the repository
  • reexec() wraps writes in a transaction — failed re-execution rolls back cleanly, no garbage left behind

Design Principles

  • Content-addressed — identical content stored once, forever
  • Immutable — history cannot be tampered with
  • Framework-agnostic — no adapters, no shims
  • Local-first — .vek/ directory, zero external dependencies
  • Minimal API — one function call to integrate
  • Atomic sessions — all-or-nothing batch writes
  • Portable — export/import execution chains as JSON/JSONL
  • Safe re-execution — verify without side-effects, re-execute with rollback

License

MIT

About

No description, website, or topics provided.

Resources

Stars

21 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages