Skip to main content

Journeyman

Turn any agent into a self-learning system. Your agent learns from user feedback — and every lesson must pass your evals before it goes live. Two lines of integration code.

pip install journeyman-agents        (local dev: pip install -e ".[dev]")
import journeyman as jm
jm.init()                                     # auto-instruments openai / anthropic

@jm.agent                                     # <- your agent. Any Python callable.
def my_agent(question: str, learned_context: str = "") -> str:
    # put learned_context into your prompt — that's the whole self-learning hook
    ...

my_agent("How do I reset my password?")       # traced
jm.feedback(1.0, "correct")                   # one-line learning signal
journeyman demo        # see the full flywheel on sample data (no API keys needed)
journeyman learn       # run one eval-gated learning cycle
journeyman up          # local API server (HTTP mode for other processes/languages)

What it does

Layer What you get Code required
Tracing Every run: inputs, outputs, tool calls, LLM calls, tokens, cost, latency, errors jm.init() + @jm.agent
Feedback Explicit signal bound to traces jm.feedback(score, comment)
Memory Long-term memory built automatically from your agent's experience + your docs none
Insights Lessons learned from feedback, injected back into your agent a learned_context: str = "" parameter
Evals Suites in YAML/DB, 7 scorer types incl. LLM-as-judge, full history a YAML file
The gate Learned changes only stay if the eval pass-rate holds — otherwise auto-rollback mark a suite gate: true
API server HTTP trace ingest + read/manage APIs, for other processes and languages journeyman up

The flywheel

     your agent runs                    users react
   ┌───────────────────┐            ┌─────────────────┐
   │  @jm.agent traces │──────────► │  jm.feedback()  │
   └───────────────────┘            └────────┬────────┘
             ▲                               │
             │                               ▼
   ┌─────────┴─────────┐            ┌─────────────────┐
   │ learned_context   │            │  learning cycle │  journeyman learn
   │ (lessons your     │ ◄──────────│  new lessons    │
   │  agent earned)    │   applied  │  EVAL GATE      │──► rolled back if
   └───────────────────┘   only if  └─────────────────┘    pass-rate drops
                           evals hold

The learning cycle turns feedback into candidate lessons, reconciles them with what the agent already knows, and runs your gate suite before anything goes live — regressions roll back automatically. Well-rated production answers are also mined into suggested eval cases you can accept into a suite with one API call.

Works with zero config — scales with config

  • No API key? Everything runs offline with built-in heuristics. Add OPENAI_API_KEY / ANTHROPIC_API_KEY and the same pipeline upgrades itself to LLM-powered learning, LLM-as-judge, and real embeddings. Your agent's own LLM stack is untouched either way.
  • No server? The SDK writes to an embedded SQLite db (.journeyman/). journeyman up reads the same file. Set JOURNEYMAN_SERVER=http://host:port to ship traces over HTTP instead (works from other processes/languages — POST /api/traces).
  • No config file? Fine. journeyman init writes an optional journeyman.yaml:
project: my-bot
entrypoint: app.main:my_agent      # lets the CLI/server run your agent for evals
learning:
  gate_suite: smoke                # the eval gate
  regression_threshold: 0.05
  auto_minutes: 0                  # >0: server runs learning cycles on a timer

Eval suites

# suite.yaml  ->  journeyman eval --load suite.yaml
name: smoke
gate: true
cases:
  - input: "How do I reset my password?"
    expect_contains: "portal.acme.com"
  - input: "VPN isn't connecting on my Mac"
    expect_contains: "6.2"
  - input: "Summarize our refund policy"
    judge: "Answer must state the 30-day window and the store-credit exception."

Checks: expect_exact, expect_contains, expect_contains_any, expect_not_contains, expect_regex, judge (binary LLM-as-judge), and scorer: module:fn for custom Python.

Safety guarantees of the SDK

  • Never raises into your code; internal failures degrade to no-ops (one warning).
  • Never blocks your hot path — persistence happens on a background thread with a bounded queue (drops, never blocks). jm.flush() for scripts/serverless.
  • KeyboardInterrupt/SystemExit always propagate; your exceptions are recorded and re-raised unchanged.
  • JOURNEYMAN_DISABLED=1 is a true kill switch.
  • jm.status() tells you exactly what's running and where data goes.

Other languages

The learning loop runs in the server, so other languages need only a thin client. Official SDKs, same safety contract as Python (never throw, never block, kill switch):

  • TypeScript / JavaScriptsdks/typescript (Node 18+, zero dependencies)
  • Gosdks/go (standard library only)
import * as jm from "journeyman-agents";
const myAgent = jm.agent(async (q, learnedContext) => { /* your agent */ });
await myAgent("How do I reset my password?");
jm.feedback(0.0, "wrong — the portal moved");

Anything else can speak the HTTP API directly: POST /api/traces, POST /api/feedback, GET /api/recall?q=... against journeyman up. Full guide for all three paths: docs/SDKS.md.

Python API

jm.init(project=..., autolog=True, server=None, db=None)   # all optional
@jm.agent / @jm.tool / @jm.step        # decorators (bare or with args; sync or async)
jm.wrap(fn)                            # functional form
with jm.trace("name", input=...):      # for code you can't decorate
jm.feedback(score, comment, trace_id=None)
jm.recall("query")                     # the learned-context block, on demand
jm.evaluate(fn=None, suite=None)       # run a suite from Python
jm.learn()                             # run a learning cycle from Python
jm.record_llm(model, input, output, tokens_in, tokens_out)  # custom LLM clients
jm.flush(); jm.status()

How much better does it get?

A working retrieval agent — it reads documents, extracts answers, picks options — answers four public benchmarks. It gets most of them wrong, which is the point: that's the starting line. Users correct its mistakes on the original wording, one learning cycle runs, and then it faces the same questions reworded, so it can't have memorised anything.

Benchmark Scored by Before After
SQuAD (40-document corpus) F1 18% 78%
HotpotQA (two-hop, 8 decoys per question) F1 8% 100%
MMLU (college & professional exams) exact match 18% 75%
ARC-Challenge (science reasoning) exact match 20% 88%
Average — 200 questions 16% 85%

16% → 85%, a 5.4× improvement, from 174 corrections and one learning cycle that takes 12 seconds. Both columns are the same agent on the same reworded questions; the only difference is whether it has the lessons. Reproduce: python bench/improve.py.

What happens when the feedback is wrong?

This is the question every "learns from your corrections" tool skips, and it's the one that costs money. Take an agent that already works, hand it 10 confidently wrong corrections per benchmark, run a learning cycle, and measure how much of it still answers correctly:

Answers still correct after 70 wrong corrections Keyword log Journeyman
Across all questions 74% 97%
On the questions the bad feedback targeted 0% 91%
On untouched questions 99% 99%

Every batch is tested against your eval suite before it goes live and kept only if the pass rate holds. A lookup table has no equivalent — it applies whatever it's told, immediately. Reproduce: python bench/robustness.py.

Weakest benchmark: MBPP at 82%. The gate is exactly as good as the evals you give it, and 20 cases didn't cover enough of the poisoned tasks. Full detail in docs/BENCHMARKS.md.

Development

python -m venv .venv
.venv/Scripts/python -m pip install -e ".[dev]"
.venv/Scripts/python -m pytest tests

Docs: docs/BENCHMARKS.md (what's measured and how), docs/SDKS.md (TypeScript, Go, and HTTP integration), CONTRIBUTING.md.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

journeyman_agents-0.1.1.tar.gz (995.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

journeyman_agents-0.1.1-py3-none-any.whl (53.7 kB view details)

Uploaded Python 3

File details

Details for the file journeyman_agents-0.1.1.tar.gz.

File metadata

  • Download URL: journeyman_agents-0.1.1.tar.gz
  • Upload date:
  • Size: 995.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for journeyman_agents-0.1.1.tar.gz
Algorithm Hash digest
SHA256 106ec131b3b9363907c14276eb5affd0c7760936cb23ccc54b41b97072b58789
MD5 1ff52f71dfdc6c765bd5d1173d0faab9
BLAKE2b-256 821215a5f758ba10171d83f032344281ac88f0d008b2174341ae241216d72cce

See more details on using hashes here.

File details

Details for the file journeyman_agents-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for journeyman_agents-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 816c2a2748e1aa5a9f59f1629b7413b60354c885bcfcf95dd2d6a4f27dc1ad3b
MD5 bd72ee11c4bca53407ec6499ac9462ca
BLAKE2b-256 9faf944986fa6193b762a1ce052fb5c2e7f78804b0c6f5c8927a0da517a27c8d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page