A proposal for turning bada.im into a threaded, always-working orchestrator. It hands coding work to Claude Code, Codex, Kimi, Venice-backed agents and local Ollama models, keeps working through a backlog on its own, and never spends the last of any plan, so there is always room left for Jay to work by hand.
Written 16 October 2026. Nothing on this page is built, installed or keyed. Venice facts were read from Venice's own docs and model page that day (sources V1 to V8 at the end); model names and prices change monthly, so check them again before relying on them. Facts about this machine were read from it, or from the handoff README.
Our reading of the request: "it" is the setup analysed in A second brain on one laptop, as revised in its section 7. In short:
Two more readings, both inferred rather than confirmed. "Like Claude Code with threads" means the way this project already works: each request becomes a thread with its own agent, its own checklist and its own result, and a coordinator watches them all. "Like dot" means the Codex agent that signs itself "dot/Codex" on our agent collaboration page, which picks up queued goals and keeps going without being prompted each time. If either reading is wrong, sections 4 and 5 change; the rest doesn't.
This page answers three things: how to get a Claude Code or Codex style coding agent running on Venice (section 2), where Hermes fits (section 3), and how bada would orchestrate all of it with a reserve left on every plan (sections 4 to 8).
Venice serves an OpenAI-compatible API at https://api.venice.ai/api/v1, so any agent harness that accepts a custom
OpenAI-style endpoint can use it. V1 Venice's own integration list names Claude Code, Codex CLI, OpenCode, Aider, Cline, Cursor,
Kilo Code and Hermes Agent. V2 It does not document an Anthropic-format endpoint, which matters for Claude Code.
| Harness | Open? | How it reaches Venice | Fit for us |
|---|---|---|---|
| Codex CLI, a second profile | Apache 2.0 | A [model_providers.venice] block in ~/.codex/config.toml with wire_api = "responses", selected by a profile. V3 |
Already installed (0.162.1). Same harness, same AGENTS.md, same telemetry; only the model changes. The cheapest experiment by far. |
| OpenCode | MIT | Venice as a custom provider in opencode.json, models named venice/<id>. V4 |
The best open, vendor-neutral fallback: it speaks to Venice, Ollama, Anthropic and OpenAI alike. Not installed. |
| Hermes Agent (Nous Research) | MIT | Custom endpoint in ~/.hermes/config.yaml, key from VENICE_API_KEY. V5 |
The most "dot-like" of the lot: its own cron scheduler, memory, subagents and chat gateways. V6 Also the biggest and most opinionated; see section 3. |
| Aider | Apache 2.0 | OpenAI-compatible settings. | Good git-native pair programmer for single changes; less suited to long unattended tasks. |
| Claude Code via claude-code-router | Claude Code no; the router is open source | A local proxy translates Claude Code's Anthropic requests into Venice's OpenAI format. V7 | Works, but it needs Node (not installed), puts a third-party proxy between Claude Code and every request, and Claude models through Venice are "anonymized" proxies billed per token. We already have Claude Code on its own subscription. Not recommended. |
Venice splits its catalog into "private" models it runs itself without logging prompts, and "anonymized" ones it forwards to OpenAI, Anthropic and others, who then see Venice as the customer. V5 V8 For code we'd use the private, open-weight ones, which is also what makes Venice worth having next to the subscriptions we already pay for:
| Model (Venice id) | Privacy | $ in / out per 1M | Role |
|---|---|---|---|
Qwen3 Coder 480B Turbo (qwen3-coder-480b-a35b-instruct-turbo) | Private | 0.35 / 1.50 | Bulk coding, cheap enough to leave running. |
Kimi K2.7 Code (kimi-k2-7-code) | Private | 0.75 / 3.50 | Harder changes; also a second route to Kimi when the Kimi plan is low. |
GLM 5.3 (z-ai-glm-5-3) | Private, 1M context | 1.75 / 5.50 | Long-context reading of a whole repository. |
DeepSeek V4 Pro (deepseek-v4-pro) | Private, 1M context | 1.65 / 3.30 | Second opinion and review. |
Hermes 3 Llama 3.1 405B (hermes-3-llama-3-1-405b) | Private | 1.10 / 3.00 | Writing and general tasks, not coding (section 3). |
Prices as listed on venice.ai/models on 16 October 2026. V8 The ids differ between Venice's own pages, so the adapter should read
them from GET /models rather than hard-coding them.
Our pick: start with a venice profile in the Codex CLI we already run, pointed at Qwen3 Coder, and add
OpenCode as the open harness once that works. Two harnesses on one endpoint lets us tell a weak model apart from a weak harness. One change from
Venice's own guide: it puts the key straight into config.toml as experimental_bearer_token. V3 Our rules
(AGENTS.md section 13) don't allow that, so the profile reads it from the environment instead:
# ~/.codex/config.toml (proposed, not applied)
[model_providers.venice]
name = "Venice"
base_url = "https://api.venice.ai/api/v1/"
env_key = "VENICE_API_KEY" # Jay stores the key; nothing is written here
wire_api = "responses"
[profiles.venice]
model_provider = "venice"
model = "qwen3-coder-480b-a35b-instruct-turbo"
# use: codex --profile venice exec "…"
"Hermes" names two different things, and both are relevant.
Venice lists one Hermes model, Hermes 3 Llama 3.1 405B, a 2024 general-purpose model. V8 The newer Hermes 4 (70B and 405B) is not on Venice's API; there is an open user request asking Venice to add it. Hermes 4 is served by Nous Portal and OpenRouter. H1 H2 Neither is tuned for agentic coding the way Qwen3 Coder, Kimi K2.7 Code or GLM are, so we'd use Hermes for writing, summarising and general reasoning, and keep it out of the coding route unless a measurement on our own tasks says otherwise.
Hermes Agent is Nous Research's open-source (MIT) agent: a CLI with a built-in cron scheduler that runs tasks written in plain language,
agent-curated memory with full-text search of past sessions, skills it writes for itself after hard tasks, parallel subagents, and one gateway
process for Telegram, Discord, Slack, Signal and email. It can also serve itself as an OpenAI-compatible endpoint. V6 H3 It speaks to any
/v1/chat/completions server, so Venice, Ollama or OpenRouter all work.
It is closer to "dot" than anything else here, which raises the obvious question: why not just run Hermes as the orchestrator?
| Hermes Agent as the orchestrator | bada as the orchestrator, Hermes as one worker |
|---|---|
| Working in days: install, point at Venice, write cron tasks. | Weeks: we build the scheduler, ledger and UI. |
| Knows nothing about our Claude, ChatGPT and Kimi subscription windows, so it can't keep a reserve on them. | The reserve is the core feature (section 6). |
| State lives in its own memory and skill files, which it rewrites itself. | State lives in Postgres and git, where we can read, test and export it. |
Python, with a curl | bash installer, outside our Ruby-first rule. | Ruby and Rails, per AGENTS.md sections 5 and 9. |
| Chat gateways come built in. | Threads are web pages on bada.im; chat can come later. |
Our pick: Hermes Agent is a worker behind an adapter, the same as Codex or Kimi, so we can try its memory and
skills on real tasks without handing it the keys to every plan. If it turns out to do the orchestration better than our own code, swapping the
adapter is cheap. Read its installer before running it, and run it with the local terminal backend in a worktree, never with access to
~/.config/environment.d.
bada is a Rails app on this laptop. A thread is one goal written by Jay, with its conversation, its checklist and its outputs, like a thread in this project. Each thread breaks into tasks, and each task is carried out as a run: one agent CLI, in one git worktree, with a time and token limit. A scheduler loop keeps picking the next task whenever a plan has room, so work continues while Jay is away; that is the "dot" half. The public bada.im pages stay static; the app sits behind sign-in at a path on the site.
Data first (AGENTS.md section 7). Every table carries organization_id and rooftop_id from the first migration,
with PostgreSQL row-level security, as section 15 requires; today there is one organization and one rooftop.
| Table | Holds |
|---|---|
threads | Goal, status (open, working, waiting on Jay, done), owner, standing or one-off. |
messages | The thread conversation: Jay's words, agent replies, approvals. |
tasks | One unit of work: acceptance checks, state (proposed → ready → running → review → done, or blocked), estimate, repository and base commit. |
runs | One attempt at a task: provider, model, worktree, start and end, exit, transcript location, tokens in and out, cost. |
providers | Each adapter and its models: Claude Code, Codex, Codex-on-Venice, Kimi, OpenCode, Hermes Agent, Ollama. |
plans | What we pay for and how it's limited: window type (rolling hours, weekly, daily epoch, monthly money), limit, reserve, and how remaining quota is read. |
usage_events | Append-only: every run's usage, and every reading of a plan's remaining quota, with its source. |
decisions | Every routing or "is it done" question asked of the decision model, its options, answer, probability, and the outcome we saw later. |
Transcripts and diffs stay as files in git worktrees and a data folder named in config; the database points at them. Everything exports as SQL dumps and plain files.
This is the part no off-the-shelf harness does for us, and the reason bada is worth building. The everyday habits behind it, done by hand today, are in Token maxxing.
For each plan, unattended work may only spend up to limit − reserve in the current window. The reserve belongs to Jay. A run starts only if its estimated cost, at the 90th percentile of similar past runs, fits under what's left. If no plan has room, the task waits; it never borrows from a reserve. Interactive use by Jay counts against the same ledger but is never blocked by it.
This is deterministic Ruby, not a model's judgment. The decision model picks among the plans the rule allows and can't widen the list.
| Plan | Window | How we'd read remaining quota | Default reserve |
|---|---|---|---|
| Claude (Claude Code subscription) | Rolling hours plus weekly | Our own count of tokens per run from claude -p --output-format stream-json and the OTel data it already sends. The remaining allowance
isn't something we've confirmed Claude Code exposes to scripts, so the limit is set by Jay and corrected whenever a run reports "limit reached". | 30% |
| ChatGPT (Codex) | Rolling hours plus weekly | codex exec --json emits token counts per turn, and a rate-limit block when the server sends one. In our latest local session it was empty, so
we fall back to our own count, as for Claude. | 30% |
| Kimi | Plan quota | Our own count from kimi -p --output-format stream-json; limit set by Jay. | 30% |
| Venice | Daily epoch (DIEM) or a money balance (USD) | The best of the lot: GET /api_keys/rate_limits returns USD, DIEM and bundled-credit balances, per-model limits and when the next epoch
begins. V9 One DIEM is $1 of compute a day; USD credits don't expire. V10 | 25% of the day |
| Ollama (local) | None, but one 4 GB GPU | Not money but time: one run at a time, and paused while the radio app or Whisper needs the GPU. | n/a |
| Jev (TypeSafe) | Pay per call | Monthly money cap set by Jay; Laya on this machine is the default, so Jev calls should be rare. | monthly cap |
The reserve percentages are starting guesses for Jay to change, not measurements. Plan names and limits aren't quoted because they change; the
plans table holds whatever is true this month.
Typed questions only, each logged in decisions so we can score them later (AGENTS.md section 17): choice of which allowed
provider takes a task, condition for whether a run's result meets its acceptance checks well enough to send to review, and score
for how likely a task is to need a strong model. A wrong answer costs a retry, never a reserve or an unapproved release. Laya runs here by
default; Jev sits behind the same adapter and can be compared on the same logged questions once Jay's key is stored.
bada.im is an adversarial research site, so the proposal has to survive its own threat model.
| Failure | What stops it |
|---|---|
| A web page or file an agent reads tells it to push, publish or exfiltrate (prompt injection). | Runs get only their own worktree, no secrets beyond their own provider key, and no push or publish rights. Those actions happen only in bada, after an approval in the thread. |
| An unattended agent runs with its "never ask" mode on and deletes or rewrites things. | Each harness's sandbox stays on; work is in a disposable worktree; the merge into a branch is a separate, reviewed step. |
| A loop of follow-up tasks burns a whole plan overnight. | Reserves, a per-thread token cap, a per-day cap on new tasks, and follow-ups start as proposals, not ready work. |
| A model decides its own work is finished. | A different provider reviews, and acceptance checks are commands that pass or fail. |
| A provider goes away or changes prices. | Every provider is one adapter class and one row in plans (AGENTS.md section 11). |
| A key leaks into a transcript or a page. | Keys only through Secrets.fetch; transcripts are scanned for secret patterns before they are stored or shown. |
| The decision model is fooled into routing badly. | It only chooses among options the budget gate allowed, and its choices are logged and scored. |
| Rule (AGENTS.md) | How bada meets it |
|---|---|
| 5, 9: Ruby first, Rails for a real app with a database | Rails with its defaults: Postgres, Solid Queue for the scheduler, Hotwire for live thread pages. One app in apps/bada/. |
| 11: open, self-hosted, two swappable providers | Seven agent adapters, two decision adapters (Laya, Jev), Venice reachable through two harnesses. Data in Postgres and git. |
| 12: observability | bada-web and bada-worker registered in observability/services.yml; every run is a span with provider, model, tokens, cost and outcome. |
| 13: secrets | VENICE_API_KEY and TYPESAFE_API_KEY stored by Jay, read with Secrets.fetch; names listed in apps/bada/.env.example. |
| 14: twelve-factor | Port from PORT on 127.0.0.1, config from env, logs to stdout, one systemd unit per process type, safe to restart mid-run (runs resume or are marked failed). |
| 15: identity | Tenant columns and row-level security from the first migration; sign-in through ngrok's Google sign-in today, OIDC to our broker when it exists. |
| 17: testing | Minitest. The budget gate, reserve maths and state transitions get hand-worked examples; adapters are tested against recorded CLI output. |
Each step has a check, and each is useful on its own if we stop there.
VENICE_API_KEY; we add the profile from section 2. Check: codex --profile venice exec fixes a
seeded bug in a scratch repository, and the run shows up in Grafana./status or dashboard within a stated margin for one week.Missing on this machine for this plan: Postgres and Node (Node only for claude-code-router, which we don't recommend). OpenCode and Hermes Agent install as user-local tools. No Venice key is stored yet.
Provided as is, for information only, with no warranty and no liability. Not legal or professional advice. Security and radio material is for authorized, lawful use only. Full disclaimer.
Visits are logged on our own server: IP address, browser and device details, and pages viewed. We use them to understand traffic and spot attacks, and never share or sell them.