lobes

Every machine on the Culture mesh thinks locally. lobes is the tool that makes that true: it runs, assesses, and switches the OpenAI-compatible models a machine serves — not as one monolithic endpoint, but as specialized lobes, each with a role.

One command surface, dry-run by default, built for agents to operate. This page is the tour.

  • installuv tool install lobes-cli
  • repoagentculture/lobes-cli
  • commandlobes
  • validated onDGX Spark · Jetson Thor
  • shapesmachine-as-brain · spark-lobe · thor-lobe
  • nextJetson AGX Orin (JetPack 7.2)
the lobes

One machine serves a small fleet of minds

A machine running lobes serves a small fleet: an always-warm text primary, a multimodal gear, tiny embedding and reranking gears, audio in and out — fronted by one gateway that routes each request by its model field. Callers address a lobe by role — cortex, senses, embedder, reranker — and never need to know which checkpoint answers.

Every verb speaks --json, results go to stdout and diagnostics to stderr, and every write verb is a dry run until you say --apply. Agents call CLIs in loops; safe-by-default is not a nicety here, it is the contract.

  • cortex

    reasoning, deciding, planning — final authority

    Qwen3.6 27B NVFP4
  • senses

    intake, vision, classify intent, speak back

    Gemma 4 12B NVFP4A16
  • embedder

    vectorization, memory retrieval

    Qwen3 Embedding 0.6B
  • reranker

    retrieval ordering, relevance

    Qwen3 Reranker 0.6B
  • stt

    hearing — audio in, text out

    Parakeet TDT 0.6B
  • tts

    voice — text in, audio out

    Chatterbox
the command

Watch it run — these are real captures

The tour in four verbs: whoami tells you which machine and which model. status tells you the configured model and container health. switch changes the served model — showing you the full resolved config before touching anything. And capabilities tells you, machine by machine, which lobes are ready.

sparkone machine, many lobescaptured 2026-07-14
$ lobes whoami
tool: lobes
version: 0.40.1
machine: spark-f8a9 (GPU 0: NVIDIA GB10)
served_model: sakamakismile/Qwen3.6-27B-Text-NVFP4-MTP  port: 8001
gear: balanced / spark
$ lobes status
  model-gear-vllm-primary — running (healthy)
  model-gear-vllm-multimodal — running (healthy)
  model-gear-vllm-embed — running (healthy)
  model-gear-vllm-rerank — running (healthy)
  model-gear-gateway — running (healthy)
  model-gear-stt — running (healthy)
  model-gear-chatterbox — running (healthy)
  … health: ok (:8001)
sparkprofiles — dry-run firstcaptured 2026-07-14
$ lobes switch sakamakismile/Qwen3.6-27B-Text-NVFP4-MTP \
  --purpose decode-heavy --machine thor
DRY RUN — would update ~/.lobes/.env:
  VLLM_PURPOSE=decode-heavy
  VLLM_MACHINE=thor
  VLLM_MAX_MODEL_LEN=32768
  VLLM_GPU_MEM_UTIL=0.6
  VLLM_ATTENTION_BACKEND=flashinfer
  VLLM_MAX_NUM_SEQS=2
  VLLM_MAX_NUM_BATCHED_TOKENS=4096
  tool-call parser (auto-selected): qwen3_coder
  quantization (from catalog): modelopt
Re-run with --apply to execute.
profiles

Tuned by purpose × machine, open to override

A model never runs bare. lobes resolves its serve config through three layers — the machine profile, the workload purpose, and the model's own catalog entry — and any explicit flag overrides them all.

That last clause is the point: the profiles are shipped defaults, not fences. New machine? Add a profile. Different workload? Pass --purpose, or override a single knob with a flag. Open for extension, open for override.

workload — --purpose

purposebatchingshape
balanced4 seqs · 8192 batched tokens≈1K in / 1K out
prompt-heavy4 seqs · 16384 batched tokens≈8K in / 1K out
decode-heavy8 seqs · 4096 batched tokens≈1K in / 8K out

machine — --machine

machinehardwarestatus
sparkDGX Spark — GB10, 128 GB unifiedvalidated
thorJetson Thor — unified memoryvalidated
blackwellRTX PRO 6000 — dedicated VRAMconfigured
orinJetson AGX Orin — JetPack 7.2planned

Explicit flags always win — --max-model-len, --gpu-mem-util, or a new machine profile of your own. Full tables and measured numbers: docs/tuning-profiles.md.

the mesh-brain

The brain shape you choose

Here is the part worth leaning in for. When this page first went up, this section described a direction. As of lobes 0.42.0 it describes a shipped choice: a deployment shape — which of the six lobes a box hosts. machine-as-brain, the default, keeps the whole brain on one box, exactly as before. The mesh shapes give each box the lobes it is best at: spark-lobe keeps the Qwen cortex and drops Gemma senses; thor-lobe keeps Gemma senses and drops the Qwen cortex.

The reason is arithmetic. Co-residency taxes every lobe: sharing the Spark, cortex is trimmed to 131072 context at 0.30 GPU util so senses can fit alongside. Move the box to its shape — lobes init --shape spark-lobe, dry-run by default, --apply to commit — and cortex gets its machine back: 262144 context, the checkpoint's full native window, at 0.44 util. The mirror move on Thor serves senses at 131072, four times its 32768 co-resident trim. Both shapes were validated live on the physical boxes on 2026-07-14; the numbers are deployed env values, not estimates.

And a dropped lobe is dropped honestly. capabilities flags it, /v1/models omits it, and a request for it returns 404 role_infeasible — never a silent reroute to a different model. Each box tells the truth about what it hosts, so composing boxes into one brain stays addressing, not archaeology.

sparkthe co-residency tax, livecaptured 2026-07-14
$ grep -E '^(PRIMARY|MULTIMODAL)_(GPU_MEM_UTIL|MAX_MODEL_LEN)' \
  ~/.lobes/.env
PRIMARY_MAX_MODEL_LEN=131072    # cortex: 128K served …
PRIMARY_GPU_MEM_UTIL=0.30       # reduced from 0.45 …
MULTIMODAL_MAX_MODEL_LEN=32768  # senses: 32K served … trimmed from 128K to free KV for cortex@128K
MULTIMODAL_GPU_MEM_UTIL=0.14    # senses@32K provisional …
sparkone safe command reclaims itcaptured 2026-07-14
$ lobes init --shape spark-lobe
DRY RUN — would scaffold the fleet duo (main + multimodal) into /home/spark/.lobes:
  docker-compose.yml (exists; needs --force to overwrite)
Profile: spark (auto-detected: device_name='NVIDIA GB10', compute_capability='sm_121', total_memory_gb=121.7)
Shape: spark-lobe (hosts=['cortex', 'embedder', 'reranker', 'stt', 'tts'])
  would set 16 env var(s) in .env
  docker-compose.shape.yml (parks vllm-multimodal in the inert 'shape-dropped' profile; …)
Re-run with --apply to write.
$ lobes init --shape spark-lobe --json | python3 -m json.tool
        "PRIMARY_GPU_MEM_UTIL": "0.44",
        "PRIMARY_MAX_MODEL_LEN": "262144",
        "MULTIMODAL_FEASIBLE": "false",

machine-as-brain — the default: the whole brain on one box

mesh shapes — shipped: each box hosts the lobes it is best at

sparkits own full braincaptured 2026-07-14
$ lobes fleet status
gateway: ok (:8001)
  model-gear-vllm-primary — running (healthy)
  model-gear-vllm-multimodal — running (healthy)
  model-gear-vllm-embed — running (healthy)
  model-gear-vllm-rerank — running (healthy)
  … 8 containers healthy
models: Qwen3.6-27B-Text-NVFP4-MTP,
        gemma-4-12B-it-NVFP4A16,
        Qwen3-Embedding-0.6B, Qwen3-Reranker-0.6B, …
thorsame contract, one hop awaycaptured 2026-07-14
$ curl -s http://thor:8000/health
{"status": "ok",
 "service": "model-gear-gateway", "version": "0.40.1"}
$ curl -s http://thor:8000/v1/models
{"data": [
  {"id": "sakamakismile/Qwen3.6-27B-Text-NVFP4-MTP"},
  {"id": "coolthor/gemma-4-12B-it-NVFP4A16"},
  {"id": "Qwen/Qwen3-Embedding-0.6B"},
  {"id": "Qwen/Qwen3-Reranker-0.6B"} ]}
$ curl -s http://thor:8000/capabilities
{"cortex":   {"model": "…Qwen3.6-27B…", "ready": true,
   "responsibilities": ["reasoning", "deciding", …]},
 "senses":   {"model": "…gemma-4-12B…", "ready": true},
 "embedder": {"ready": true}, "reranker": {"ready": true},
 "stt": {…}, "tts": {…}}
thorask a lobe by role, from anywherecaptured 2026-07-14
$ curl -s http://thor:8000/v1/chat/completions \
  -d '{"model": "cortex", "messages": [{"role": "user", "content": "Introduce yourself."}]}'
"Greetings from the Cortex Lobe on Thor; I am a vital thread in our collective mesh, and I am delighted to connect with you."

The far end of the axis is specced, not shipped — and the spec has converged (lobes-cli #112), its decisions recorded: one heavy lobe per box, with the cheap gears (embedder, reranker, stt, tts — about 0.06 GPU each) co-residing on every box that wants them. Cross-box reachability is direct + honest referral: no data-plane proxying — with opt-in peer config, a box's capabilities and 404s name the peer that hosts the role it dropped.

The named next step: the Jetson AGX Orin 64GB joins the mesh brain as its small-model lobe once JetPack 7.2 brings the software stack. Its shape ships as declared-but-unvalidated data until a physical Orin boots it and its probes pass — the same house rule this page follows: no claim outruns a live transcript.

benchmarks

Measured, and reproducible from the repo

Every deployment claim above is measured, and the harness ships in the box. lobes benchmark measures decode throughput and prefill latency — its request shape follows the configured --purpose, so the numbers track what the machine is actually tuned for. lobes assess runs correctness probes against the served model, in markdown ready for a per-model doc.

The setup is not a lab secret: the profiles are a pure data module, the compose templates are packaged in the repo, and each runtime model has a doc recording how it ran, its live test results, and its caveats. Clone it, run the same two verbs, compare.

lobes is open source, agent-first, and one of a fleet — sibling to culture, the workspace its models think inside. The captures on this page were taken live on 2026-07-14; nothing was invented.

Read the code →