Directory Structure
A scaffolded project (see Installation) looks like this:
my-agents/
├── adapters/
│ ├── cli.ts # run one turn from a terminal or script
│ └── http.ts # HTTP server — /messages, /stream, the Web UI
├── agents/
│ └── example-agent/
│ ├── index.ts # AgentConfig — name, systemPrompt, model
│ ├── actauth.yml # permission rules for this agent
│ ├── tools/
│ │ ├── index.ts # exports the `tools` array
│ │ └── get_weather.ts
│ └── skills/
│ └── convert-temperature/
│ └── SKILL.md
├── agent-registry.ts # discovers agents/* — nothing to register by hand
├── package.json
├── tsconfig.json
└── .env.example
adapters/
cli.ts and adapters/http.ts are yours — generated once at scaffold
time, then never touched again by loopengine itself. Edit them freely;
npx loopengine run/serve/dev are thin wrappers that just shell out
to your own copy of these files. See Web UI for what
http.ts serves beyond the /messages API.
agent-registry.ts
Every adapter resolves "which agent" through this file. Defining a new
agent means adding a folder to agents/ that exports config (and
optionally createModelCall) — nothing here or in any adapter needs to
change. It scans that directory and keys each entry by
AgentConfig.name, not the folder name, at import time.
agents/<name>/
One folder per agent, auto-discovered. See Add an Agent for the full field-by-field breakdown — in short:
index.ts— theAgentConfig: name, system prompt, model, and (usually omitted, since they default to the paths below)tools,rules,skillsDirs.actauth.yml— permission rules. Missing entirely means deny everything.tools/index.ts— exports atoolsarray. Missing means no tools.skills/— one subfolder per skill, each with aSKILL.md. Missing means no skills.subagents/— not a config field, a folder convention: drop another agent's folder here and it becomes one of this agent's tools automatically, merged on top oftools/.
Everything else
package.json and tsconfig.json are ordinary — loopengine is just a
dependency. .env.example documents the environment variables the
runtime reads directly (API keys, PORT, REDIS_URL,
LOOPENGINE_ADMIN_AUTH) — see Basic Configuration.