trajectorykit

A lightweight, local-first agentic framework with tool calling, recursive sub-agents, and full execution tracing.


License
MIT
Install
pip install trajectorykit==0.1.0

Documentation

🤖 TrajectoryKit: An Agent Starter Pack

A lightweight, local-first agentic framework for HuggingFace models with built-in tool calling, recursive sub-agents, and full execution tracing.

License: MIT Python 3.12

🏎💨 Quickstart

from trajectorykit import dispatch

result = dispatch(
    user_input="Compare the stats of Blue Eyes White Dragon vs Dark Magician",
    turn_length=5,
    verbose=True
)

print(result["final_response"])

The agent writes and executes code in a sandbox, returning results with inline images:

Yu-Gi-Oh Card Stats Comparison

✨ Features

  • 🏠 100% Local — runs on your own GPU via vLLM, no API keys needed
  • 🔄 Agentic Loop — iterative tool calling until the task is done
  • 🤖 Recursive Sub-Agents — spawn child agents to decompose complex tasks (up to 3 levels deep)
  • 💻 Sandboxed Code Execution — run Python (and 40+ languages) in an Apptainer sandbox with file I/O
  • 🔍 Web Search — built-in Google search via SerpAPI
  • 📊 Full Execution Tracing — every turn, tool call, token count, and sub-agent is recorded
  • 🌐 HTML Trace Viewer — self-contained dark-themed trace pages with collapsible reasoning, inline images, and token stats

📦 Package Structure

src/trajectorykit/
├── __init__.py       # Public API: dispatch, EpisodeTrace, render_trace_html, render_trace_file
├── config.py         # Model, API URL, traces directory, system prompt
├── agent.py          # Core agentic loop with tool dispatch and trace building
├── tool_store.py     # Tool definitions + wrapper functions
├── tracing.py        # Dataclasses, pretty-print, JSON/HTML serialization
├── examples.py       # Ready-to-run examples
└── serve_vllm.sh     # Script to launch vLLM server
traces/               # Auto-created directory for saved traces (JSON + HTML)

🛠 Built-in Tools

Tool Description
execute_code Run code in a sandboxed Apptainer container. Supports file upload (files) and retrieval (fetch_files) as base64.
search_web Google search via SerpAPI. Returns titles, snippets, and links.
get_current_time Returns the current date and time.
add_numbers Adds two numbers (demo tool).
spawn_agent Spawns a recursive sub-agent with its own tool access and trace.

🔁 Recursive Sub-Agents

Dispatch can spawn child agents to handle subtasks independently. Each sub-agent runs its own agentic loop with full tool access and produces its own trace, nested inside the parent's trace tree.

from trajectorykit import dispatch

result = dispatch(
    user_input=(
        "How has the market price of the card 'Blue-Eyes White Dragon' moved over the last years?"
    ),
    turn_length=5,
    max_tokens=4096
)

result["trace"].pretty_print()

Max recursion depth is controlled by MAX_RECURSION_DEPTH in config.py (default: 3).

📜 Tracing

Every dispatch() call returns a full execution trace in result["trace"].

Pretty-print to terminal

result["trace"].pretty_print()
🏁 Agent [root]  trace_id=154b9f2e
  Input: What is the current time? What is 123 + 456?
  Duration: 8.42s | Turns: 2 | Tool calls: 2
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  ┌─ Turn 1 (4.00s)
  │  🔧 get_current_time({}) [0.01s]
  │     → 2026-02-19 21:04:29
  │  🔧 add_numbers({"a": 123, "b": 456}) [0.00s]
  │     → 579
  └─
  ...
📊 Episode Summary:
  Prompt tokens:        3,621
  Completion tokens:    686
  Total tokens:         4,307

Save to disk

path = result["trace"].save()
# Writes traces/trace_20260219_210429_154b9f2e.json
# Also writes traces/trace_20260219_210429_154b9f2e.html

Traces are saved to the traces/ directory automatically.

HTML trace viewer

The HTML file is a self-contained dark-themed page with:

  • Prompt at the top (always visible)
  • Stats bar — duration, turns, tool calls, sub-agents, total tokens (prompt + completion)
  • Collapsible trace detail — starts collapsed, expand to drill into turns
  • Reasoning dropdowns — model chain-of-thought shown per turn
  • Inline images — plots and generated images rendered directly
  • Final response at the bottom (always visible)

You can also render any trace JSON to HTML:

from trajectorykit import render_trace_file

render_trace_file("traces/trace_20260219_210429_154b9f2e.json")

⚙️ Configuration

All settings live in config.py:

Setting Default Description
MODEL_NAME Qwen/Qwen3-8B HuggingFace model served by vLLM
VLLM_API_URL http://localhost:3030/v1 vLLM OpenAI-compatible endpoint
MAX_RECURSION_DEPTH 3 Max sub-agent nesting depth
TRACES_DIR <repo_root>/traces/ Where .json and .html traces are saved

🚀 Running

1. Install conda env

conda env create -f environment. yml.

2. Start the Apptainer sandbox (code execution)

bash src/trajectorykit/apptainer.sh

This pulls and runs the SandboxFusion container, exposing a code execution API on http://localhost:8080.

3. Start vLLM

bash src/trajectorykit/serve_vllm.sh

4. Run an example

cd src && python -m trajectorykit.examples

API

result = dispatch(
    user_input="Your task here",
    turn_length=5,          # Max turns (None = unlimited)
    verbose=True,           # Print turn-by-turn output
    max_tokens=2000,        # Max tokens per generation
    temperature=0.7,        # Sampling temperature
)

# result keys:
result["final_response"]   # str — the model's final answer
result["turns"]            # int — number of turns taken
result["tool_calls"]       # int — total tool calls made
result["messages"]         # list — full conversation history
result["trace"]            # EpisodeTrace — full execution tree

📚 Citation

If you use TrajectoryKit in your research or project, please cite it:

@software{trajectorykit2026,
  title={TrajectoryKit: An Agent Starter Pack},
  author={Lugoloobi, William},
  year={2026},
  url={https://github.com/KabakaWilliam/TrajectoryKit}
}

License

MIT