edge-agents

June 15, 2026 · View on GitHub

The 30 MB open-source edge AI agent runtime. Run AI agents offline, on Linux.

CI Go Reference License: AGPL v3

edge-agents demo

Build an edge agent visually, deploy it to a Raspberry Pi, and let it talk to GPIO, MQTT and local SLMs — no cloud required.

Offline by default. GPIO, UART, MQTT as first-class nodes. Local SLMs alongside cloud LLMs in the same workflow. Industrial protocols (OPC-UA, Modbus) are on the roadmap.

Runs on Linux edge devices: Raspberry Pi 5 · Jetson Orin Nano · STM32MP25 · Bosch Rexroth ctrlX CORE.

Star the repo if you think AI agents belong beyond the cloud.

Today's AI agents live in datacenters. The interesting workloads — sensors, machines, vehicles, gateways — live everywhere else. edge-agents brings the agent paradigm to the devices that interact with the real world: small enough to run on a Pi 5, capable enough to drive an industrial controller, with hardware I/O as native primitives instead of REST shims.

What you can build

  • Voice assistant on a Pi with a local SLM — wake-word → STT → agent → TTS, no internet required
  • Predictive maintenance on industrial gear — live vibration stream over MQTT → LLM decides → MQTT alert
  • Local RAG on a Jetson (on the roadmap) — answers grounded in live sensor and machine state instead of the public web (today the retriever runs against an external backend; a fully on-device RAG path is in progress)

edge-agents vs other agent frameworks

edge-agentsn8nLangGraphDifyOpenClaw
Runtime size~30 MB container~500 MB DockerPython library~500 MB Docker~1 GB Docker
Offline by defaultdepends on host❌ datacenter-only
Hardware I/O (GPIO, UART, ADC) as nodes✅ first-class
On-device SLM provider✅ typed multi-endpointpartial via libs
MQTT as workflow transport✅ first-classcommunity node
Visual builder❌ code-only
Industrial protocols (OPC-UA, Modbus)on roadmapcommunity nodes

Using edge-agents

Two pieces: the engine (a small container that runs your workflows) and the fh-workflow CLI (authors, validates, and visually edits workflow files). You can run the engine without ever cloning this repo, and author workflows with a single npm i -g @foresthubai/workflow-cli.

Quickstart

The lightest path needs no clone and no Docker — just the CLI and the visual builder:

npm i -g @foresthubai/workflow-cli
fh-workflow open my.workflow.json      # opens the visual builder; Save writes back to the file

Don't have a workflow yet? Let Claude Code write one from a single sentence — see Generate workflows with Claude Code. Ready to run it on real hardware? Run the engine on the device.

Run the engine

The engine ships as a small container you build from go/Dockerfile (multi-arch, distroless, nonroot). Most edge targets are arm64 (Pi, Jetson, STM32MP2, ctrlX), so the common flow is to cross-build on an amd64 workstation and ship the result to the device:

cd go

# Cross-build for an arm64 edge device (use --platform linux/amd64 for x86 targets)
docker buildx build --platform linux/arm64 -t fh-engine:latest --load .

# Ship to an offline device: save to a tar, copy it across, load it there
docker save fh-engine:latest -o fh-engine.tar
#   scp fh-engine.tar device:/tmp/   ← then, on the device:
docker load -i fh-engine.tar
docker run --rm -p 8081:8081 fh-engine:latest

Building for the same architecture you're already on? A plain docker build -t fh-engine:latest . works too — the Dockerfile cross-compiles via TARGETARCH, so QEMU only emulates the trivial copy into the final layer.

The fh-engine:latest tag is the one a fh-workflow deploy bundle expects (its docker-compose.yml loads the image with pull_policy: never), so an image built here drops straight into a generated bundle.

The engine HTTP API listens on :8081 on all interfaces. It runs standalone by default — no control plane, no account, no outbound calls beyond LLM provider APIs. The deploy API is gated by a bearer token: set ENGINE_SECRET to enable /deploy and /stop (without it those endpoints are closed and you load a workflow via ENGINE_CONFIG_FILE instead). :8081 is meant to sit behind your own network controls, not face the public internet. Configure via ENGINE_* env vars; see go/cmd/engine/config.go.

Hardware access: the image runs as a nonroot distroless user, so reaching real GPIO, serial or analog devices needs them passed into the container with the right group — e.g. --device /dev/gpiochip0 --group-add "$(stat -c '%g' /dev/gpiochip0)" (or run with --privileged on a throwaway dev box). Pure-software workflows need none of this.

Author workflows

A workflow is a *.workflow.json file you author, validate, and open in the visual builder. Install the fh-workflow CLI from npm — no clone required:

npm i -g @foresthubai/workflow-cli
# or run it without installing:
npx @foresthubai/workflow-cli <command>
fh-workflow open my.workflow.json          # open the visual builder; Save writes back to the file
fh-workflow validate my.workflow.json      # semantic: wiring, references, types
fh-workflow check-schema my.workflow.json  # structural: types, required fields, enums
fh-workflow update my.workflow.json        # migrate a workflow to the current schema version
fh-workflow deploy my.workflow.json        # generate a self-contained deployment bundle
fh-workflow help                           # list all commands

fh-workflow open is the visual builder — the same React Flow canvas, served locally; hit Save and it writes straight back to your file. See ts/workflow-cli for the full command reference and the --static / --dev open modes.

Generate workflows with Claude Code

Describe a workflow in plain language and the workflow-generate skill writes the *.workflow.json and runs the validators for you. Install it into any project with the skills CLI — no clone required:

npx skills add ForestHubAI/edge-agents --skill workflow-generate

The skill validates by shelling out to the fh-workflow CLI, so install that too (npm i -g @foresthubai/workflow-cli). Then just describe a workflow — e.g. "read a sensor every 10s and toggle a relay" — and the skill generates and validates the file for you.

Deploy a workflow to a device

The quick path is fh-workflow deploy my.workflow.json — it inspects the workflow, asks for the values it can't infer (device paths, broker URLs, model files, API keys), and writes a self-contained bundle: docker-compose.yml, .env, the workflow, and any config files the workflow needs — plus a README.md with the build/transfer/run steps. For an on-device SLM it even drops in a llama.cpp sidecar wired to the engine over the compose network. Without a terminal (CI, a Claude Code skill) feed the answers with --values <file.json>. The rest of this section explains what ends up in that bundle — and how to assemble it by hand if you'd rather.

Prefer to drive it from Claude Code? The workflow-deploy skill runs this same flow — reading the workflow, gathering the values, and writing the bundle while keeping secrets as placeholders. Install it the same way:

npx skills add ForestHubAI/edge-agents --skill workflow-deploy

A workflow is binding-free: it declares what it needs — channels (GPIO, MQTT, …) and custom models — but not where those live on a given device. You supply the where through a few small config files mounted into the engine container alongside the workflow. See go/docs/deployment-layers.md for the file schemas and deploy-time validation rules.

What the engine reads, and when each file is needed:

FileEngine env varWhen you need it
workflow JSONENGINE_CONFIG_FILEalways — the graph itself
device manifestENGINE_DEVICE_MANIFEST_FILEonly with hardware channels (GPIO / ADC / DAC / PWM / UART) — maps a logical id to a physical /dev/…
external resourcesENGINE_EXTERNAL_RESOURCES_FILEonly with MQTT channels or custom/self-hosted models — broker connections and LLM endpoints
deployment mappingENGINE_DEPLOYMENT_MAPPING_FILEas soon as any channel or custom model exists — binds each logical id to a resource (+ index for hardware)

Rule of thumb: a workflow with no channels and only built-in catalog models (e.g. claude-haiku-4-5) needs none of the extra files — just the workflow JSON and the provider's API key. Add the mapping the moment a channel or a custom model appears; add the device manifest for hardware, external resources for MQTT and self-hosted models.

To assemble this by hand instead of with fh-workflow deploy: ship the image with the docker save / docker load flow from Run the engine and start it with docker run, mounting the files above with -v and pointing the ENGINE_* env vars at them. The repo ships no static compose.yaml; fh-workflow deploy generates one per workflow, or write your own.

Features

  • Workflow engine — typed graph runtime; nodes for LLM calls, hardware I/O, MQTT, web search, memory, control flow.
  • Multi-provider LLMs — Anthropic, OpenAI, Google Gemini, Mistral, plus a local SLM provider for llama.cpp / vLLM / Ollama / any OpenAI-compatible endpoint.
  • Visual React Flow builder — embeddable component or runnable as bundled SPA, with typed parameters and live validation.
  • Contract-typed wire format — every API generated from contract/*.yaml for both Go and TypeScript; CI fails on schema drift.

Local models (self-hosted SLMs)

Models run on the device through llama.cpp, in their own container, separate from the engine. Reference the model in the workflow as a custom LLMModel; the engine talks to its endpoint over HTTP.

The easy way is to mark that model as on-device and let fh-workflow deploy add the llama.cpp sidecar to the generated docker-compose.yml for you — reached by service name over the compose network, no host networking, no hand-written compose (see Deploy a workflow to a device).

To run the inference container by hand instead — pull its server image and point it at a .gguf model file (e.g. a quantized Gemma):

docker pull ghcr.io/ggml-org/llama.cpp:server-b8589

docker run --rm --network host -v "$PWD/models:/models:ro" \
  ghcr.io/ggml-org/llama.cpp:server-b8589 \
  --model /models/gemma-3-270m-it-Q4_0.gguf --host 0.0.0.0 --port 8090

Start it before the engine, then point the workflow's custom model at this endpoint through the deploy files (again, Deploy a workflow to a device).

Hardware and transports

  • GPIO via go-gpiocdev (digital in/out, edge triggers)
  • ADC / DAC / PWM via Linux character-device interfaces
  • UART / serial via go.bug.st/serial
  • MQTT via Eclipse Paho — topic-scoped channels for device-to-device messaging
  • Web search as a pluggable node

Digital and analog signal types are first-class in the workflow contract.

Target hardware

✅ = brought up and exercised on our own bench. We don't yet publish a per-device CI matrix, so treat these as known-good targets rather than a continuously tested guarantee.

TargetStatus
Raspberry Pi 5 (8 GB)
NVIDIA Jetson Orin Nano (8 GB)
x86 NUC (16 GB)
STM32MP25 (1 GB, Linux MCU)
Bosch Rexroth ctrlX CORE
Other Linux amd64 / arm64Works, untested
macOS arm64 / amd64Supported (development)
Bare-metal MCU (Cortex-M)Not supported by the Go engine. Contract is portable; dedicated MCU runtime is on the roadmap.

Developing edge-agents

Want to hack on the engine, the builder, or the contract? Clone the repo — go/ and ts/ are independently buildable and releasable; only contract/ edits touch both.

git clone https://github.com/ForestHubAI/edge-agents
cd edge-agents

Build from source

Go engine (requires the Go version pinned in go/go.mod):

cd go
go build ./cmd/engine
./engine                 # runs standalone by default
go test ./...            # testify-based tests

TypeScript packages (Node ≥ 20):

cd ts
npm ci
npm run dev              # Vite dev server with the visual builder → http://localhost:5173
npm run build            # build all three packages
npm run typecheck && npm run lint && npm test

The CLI from your working tree — the root package.json delegates to ts/workflow-cli, so a single root npm install (its postinstall builds the ts/ toolchain) runs the validators against your local changes instead of the published package:

npm install
npm run check-schema -- my.workflow.json   # the -- passes the path to the CLI, not to npm
npm run validate    -- my.workflow.json
npm run open        -- my.workflow.json
npm run deploy      -- my.workflow.json     # generate a deployment bundle (--values <file.json> for scripted runs)

After a git pull that changed dependencies, just run npm install again. If a stale node_modules bites you after switching branches, do a clean reinstall:

rm -rf node_modules ts/node_modules && npm install

Contract is the source of truth

Every API type is generated from contract/*.yaml for both Go and TypeScript — CI fails on drift. Never hand-edit generated bindings; edit the contract, then regenerate both sides:

cd go && go generate ./...     # → go/api/*/types.gen.go, server.gen.go
cd ts && npm run generate      # → ts/workflow-core/src/api/workflow.ts

See go/CLAUDE.md and ts/CLAUDE.md for the full contributor guide, conventions, and the domain-layer reconciliation each side needs.

Architecture

A workflow is a directed graph of typed nodes — LLM call, hardware I/O, MQTT, memory, control flow, expressions — connected by edges with one of five types: control, tool, agentTask, agentChoice, agentDelegate. The engine interprets the graph as a state machine: wait for event → execute node → transition. The contract (contract/*.yaml) is the single source of truth — Go and TypeScript both regenerate from it, CI fails on drift.

See go/CLAUDE.md and ts/CLAUDE.md for deeper architecture notes.

Repository layout

PathWhat it contains
contract/OpenAPI 3.0.3 schemas — single source of truth for Go and TS.
go/Engine binary, LLM proxy, hardware drivers, MQTT transport. Module github.com/ForestHubAI/edge-agents/go.
ts/workflow-core@foresthubai/workflow-core — headless workflow model, validation, (de)serialization. No React.
ts/workflow-builder@foresthubai/workflow-builder — React canvas component.
ts/workflow-cli@foresthubai/workflow-cli — the fh-workflow CLI + the reference SPA it serves.

Releases

  • Go runtime — tagged go/vX.Y.Z; consume with go get github.com/ForestHubAI/edge-agents/go@vX.Y.Z.
  • TypeScript packages@foresthubai/workflow-core, @foresthubai/workflow-builder, and @foresthubai/workflow-cli ship in lockstep at the same version, published to public npm.
  • Container image — built from go/Dockerfile: multi-arch (linux/amd64, linux/arm64), distroless, nonroot. Build it yourself (see Run the engine).

See RELEASING.md.

Contributing

See CONTRIBUTING and the Code of Conduct. Open an issue before any non-trivial change. Every contribution is accepted under a Contributor License Agreement that preserves the dual-licensing model.

Security

Do not open public issues for security vulnerabilities. Use GitHub private vulnerability reporting or email root@foresthub.ai. See SECURITY.md for scope and process.


Learn more

New to edge AI? These guides on foresthub.ai define the concepts edge-agents builds on:


Talk to the team

Using edge-agents in a product, need a license that isn't AGPL-compatible, or want help getting an agent onto your hardware? Talk to the people who build it at ForestHub:


License

edge-agents uses a two-tier license model designed to make the wire format and the headless workflow model maximally reusable while keeping the engine and the visual builder protected under copyleft.

ComponentLicenseWhy
contract/ (OpenAPI schemas)Apache-2.0Wire format. Third-party Python, Rust, or Java clients should be free to implement against it.
ts/workflow-core (headless model)Apache-2.0Workflow model and validation. Same reasoning — should be embeddable into any TypeScript/JavaScript project without copyleft friction.
go/ (engine, LLM proxy, drivers)AGPL-3.0-only or commercialKeeps hosted "edge-agents as a service" offerings honest. For commercial use cases incompatible with AGPL, book a call or contact root@foresthub.ai.
ts/workflow-builder (React canvas)AGPL-3.0-only or commercialSame dual-license terms as the engine.
ts/workflow-cli (@foresthubai/workflow-cli + reference SPA)AGPL-3.0-only or commercialBundles the AGPL builder; same dual-license terms.

For the AGPL components, the AGPL network clause applies — providing a modified version over a network requires making the corresponding source available to users of that service.

Third-party components retain their own licenses; see THIRD_PARTY_NOTICES and NOTICE.


Built by ForestHub — the platform for embedded and edge AI agents. Questions or a commercial use case? Book a call.