protoAgent: an open-source agent you run on your own machine, with your own models

Community Article
Published October 26, 2026

At protoLabsAI we publish quants: the Ornith GGUFs, the ThinkingCap MTP builds, the NVFP4 conversions. We make those because we run our models locally, and we run them locally because of the thing we've spent the last six months building: protoAgent, an open-source agent runtime. Today it's MIT-licensed and on GitHub, PyPI, and as a desktop app for macOS, Windows, and Linux.

Repo: https://github.com/protoLabsAI/protoAgent

What it is

protoAgent is one long-lived agent that you own. It plans, remembers, uses tools, and hands work off to other agents. You talk to it from a desktop console, or from anything else through its OpenAI-compatible /v1 API or A2A.

Everything it keeps stays in SQLite on your disk: chats, memory, the knowledge base, tasks. There's no analytics, tracking, or telemetry. Model requests go only to the endpoint you configure, and if that endpoint is a llama.cpp or vLLM server on your own box, nothing leaves the machine.

One request to the lead agent fans out to an engineer, a QA agent, their Claude Code coders, and a researcher. The org chart shows each delegate's runs live.

Answers don't have to be text. The agent can render a chart from your data, build a small working app inline in the chat, or write a PDF you can download.

The agent charts weekly revenue from a CSV and explains the drop, including what the data can't tell it.

Asked for a mortgage calculator, the agent builds one inline. Its "Send to my agent" button passes the numbers back into the chat.

You can also give it a goal with a check, such as "make every test pass", and it keeps working until the check passes.

The goal is marked achieved once `pytest` passes.

How it's built

  • LangGraph core. The agent is a create_agent graph. Middleware hooks around the model call handle context compaction, per-turn token and cost accounting, and human-approval interrupts. Conversation state is checkpointed per thread.
  • Any OpenAI-compatible model. The server never calls a model SDK directly. It talks to an OpenAI-compatible endpoint: a local llama-server or vLLM, a LiteLLM gateway in front of several providers, or a supported Claude or ChatGPT subscription. Changing models is a config edit.
  • Subagents and delegation. A task() tool spins up subagents with narrower toolsets. Other agents on your network are reachable over A2A. Coding work goes to Claude Code, Codex, or any CLI agent that speaks the Agent Client Protocol.
  • Plugins instead of forks. Tools, skills, subagents, MCP servers, scheduled jobs, and console views all ship as plugins that install from a git URL and get pinned in a lockfile.

Running it on a local model

Serve a model with an OpenAI-compatible API. For example, our Ornith 1.5 9B GGUF with llama.cpp:

llama-server -hf protoLabsAI/Ornith-1.5-9B-MTP-GGUF --jinja -c 32768 --port 8080

Then start protoAgent:

uvx --from protolabs-agent protoagent serve

Open http://localhost:7870, pick Connect a model endpoint, enter http://localhost:8080/v1, and finish the setup wizard. If you want the full console without a terminal, use the desktop app instead.

What we use it for

We don't run it as a demo. Every day we use protoAgent for:

  • A PM agent that works a project board, briefs coding agents, and merges PRs that pass review. Some of protoAgent's own PRs were written and merged this way.
  • A coding agent that hands implementation work to Claude Code and Codex, then checks what comes back.
  • A handful of narrower agents built from the same core: a career coach, a tabletop rules assistant, a fitness coach. Each one is mostly a different prompt plus a few plugins.

Here's how the PM flow looks. You ask for a feature in chat, and the agent answers with a spec form:

The agent builds a spec form for a new board card inside the conversation.

Once you submit it, the card goes onto the board, and a coding agent picks it up and builds it:

The new card moves to Building with Claude Code working on it. Finished cards in Done link to their PRs.

What was hard

Some of what we learned building on LangGraph, in case it saves you time:

  1. Streaming was where most bugs lived. Tokens, tool calls, and subagent progress have to reach the UI in order, through a gateway, over SSE and A2A. Most "the agent hung" reports turned out to be the stream, not the agent.
  2. Context windows were quietly wrong. Our lookup of each model's context size kept falling back to a default, and subagents didn't compact the way the main thread does. Long runs died with no clear error. Local servers make this worse, because the window you launched with isn't always the window the server reports.
  3. Small models loop. A model calls the same tool with the same arguments until the context is full. The fix was a detector in middleware; better prompts didn't solve it.
  4. Trace from day one. Optional Langfuse tracing is built in. Half our bugs only made sense once we could see the full trace.

Try it

Issues and PRs are welcome. We especially want reports from anyone running it on local models: which ones handle the tool loop well, and where it falls over.

Community

Sign up or log in to comment