Skip to content

Capability tools

Some things an agent wants to do are heavy: turning a Markdown memory node into a polished PDF needs a headless browser, bundled fonts, and the RAM spikes that come with them. Baking that into the core server would bloat the image, drag the API process into browser-lifecycle management, and couple a privacy-sensitive front door to a noisy dependency.

Hadron keeps the core lean instead. hadron-server stays the front door — identity, access control, decryption, node loading — and delegates the heavy work to capability tools: small, stateless, independently-deployed services that each own one provider-specific concern and expose a narrow HTTP surface.

The model

A capability tool is a separate process (its own container) that implements a pure function over its HTTP inputs:

  • No database, no keys, no access-control logic. Everything that needs identity, secrets, or the graph stays in hadron-server. The tool only ever sees content that the server has already authorized and decrypted.
  • Stateless. Give it the same input, get the same output. Nothing to migrate, nothing to back up, trivial to scale horizontally or restart.
  • Narrow surface. A handful of endpoints that do one job — "turn this document into that document" — plus health/info.

This is the same isolation boundary described in Architecture, pushed one layer out: the core owns the what and who; a capability tool owns a heavy how.

flowchart TD
    A[Agent / Portal] -->|GraphQL| S[hadron-server<br/>auth · ACL · decryption · node loading]
    S -->|HTTP · Bearer token| T[Capability tool<br/>stateless · no DB · no keys]
    T -->|result| S
    S -->|response| A

Why split it out

  • Keep the core image small. Chromium and its fonts never enter the API container.
  • Contain the blast radius. A renderer crash, a memory spike, or a zombie browser process stays in the tool, not the front door.
  • Open by design. A capability isn't hard-wired into the server. An agent that needs "render this to PDF" picks a tool advertising that capability, the server routes the request, and permission is checked at the server — more than one tool may offer the same capability. The protocol for how a tool advertises what it can do, and how the server routes to it, is still being worked out; the first tool doubles as the place that protocol gets refined.

The first tool: the PDF service

hadrontool-pdf is the first capability tool on the platform. It converts Markdown → PDF (via marked + Puppeteer/Chromium) and extracts PDF → Markdown text (via a PDF text-layer reader). It holds no database, no keys, and no access-control logic — exactly the shape above.

It is deployed internal-only: hadron-server reaches it by service name inside the private network, and every request carries a shared bearer token. It is not exposed to the public internet, so you won't call it directly — but its HTTP contract is documented for operators and for the server code that does call it. See PDF service HTTP API.

A worked example — the Portal's Download → PDF on a node:

sequenceDiagram
    participant U as Portal (user)
    participant S as hadron-server
    participant T as hadrontool-pdf
    U->>S: Download node as PDF (GraphQL)
    S->>S: access control + decryption + load node → Markdown
    S->>T: POST /convert/markdown-to-pdf (Bearer token)
    T-->>S: PDF bytes (base64)
    S-->>U: triggers browser download

The privacy invariant holds throughout: node plaintext only reaches the tool after hadron-server has done auth and decryption. The tool renders; it never decides who may read what.

Transport

Today capability tools speak HTTP, with the server and tools co-located in the same private network. A platform message bus (NATS) is the planned transport: when it lands, the same pure render/extract functions can be wrapped behind a request/reply subject without touching the rendering core.

What's next