agntz
RuntimeHostedSelf-hostDocsChangelog
Sign inQuickstart
v1.0.0 — releaseddeclarative runtimeopen source

Describe your agent.
Run it.

A declarative runtime for production agents. Define agents in YAML, call your existing APIs, and run anywhere — local, hosted, or self-hosted.

$npm install @agntz/sdkcopy
YAML in, agent out
Your existing APIs
Local · Hosted · Self-host
# agent.yaml — the whole agent, declared.
id: weather-bot
kind: llm

model:
  provider: anthropic
  name: claude-sonnet-4-6

instruction: |
  You are a friendly weather assistant.
  When asked about a city, look up the
  forecast and reply in plain language.

tools:
  - kind: http
    name: get_forecast
    description: Current weather for a coordinate.
    url: "https://api.open-meteo.com/v1/forecast?latitude={latitude}&longitude={longitude}&current_weather={current_weather?}"
    method: GET
valid · ready to run
weather-bot.yaml
The YAML is the agent. No wiring, no compose, no loop to author — the runtime runs it.
The shift

A runtime,
not a library.

Other frameworks hand you primitives and ask you to build the agent. agntz is the agent — you describe it, the runtime runs it.

With a library@anthropic-ai/sdk
Primitives. You build the agent.
With agntzdeclarative runtime
Description. The runtime runs it.
01200+ lines of glue code
30 lines of YAML
02Import, compose, wire tools
Define, run
03You own the agent loop
The runtime owns the loop
04Hand-write tool adapters
Point at your OpenAPI or manifest
05Build session + context handling
Sessions handled, context windowed
beforeimperative · same weather-bot, hand-wired
weather-bot.ts
// With a library — you wire the agent yourself.
import Anthropic from '@anthropic-ai/sdk';

const client = new Anthropic();
const tools = [{
  name: 'get_forecast',
  description: 'Current weather for a coordinate.',
  input_schema: {
    type: 'object',
    properties: {
      latitude:  { type: 'number' },
      longitude: { type: 'number' },
      current_weather: { type: 'boolean' },
    },
    required: ['latitude', 'longitude'],
  },
}];

async function callTool(name, args) {
  if (name !== 'get_forecast') throw new Error('unknown');
  const url = new URL('https://api.open-meteo.com/v1/forecast');
  for (const [k, v] of Object.entries(args)) {
    url.searchParams.set(k, String(v));
  }
  const r = await fetch(url);
  return await r.json();
}

let messages = [{ role: 'user', content: input.message }];
let safety = 0;

while (safety++ < 10) {
  const resp = await client.messages.create({
    model: 'claude-sonnet-4-6',
    system: 'You are a friendly weather assistant...',
    tools, messages, max_tokens: 1024,
  });

  // You own retries, token windowing, summarization,
  // session persistence, tracing, error handling...

  if (resp.stop_reason === 'end_turn') break;
  const uses = resp.content.filter(b => b.type === 'tool_use');
  const results = await Promise.all(
    uses.map(async u => ({
      type: 'tool_result',
      tool_use_id: u.id,
      content: JSON.stringify(await callTool(u.name, u.input)),
    })),
  );
  messages = [...messages,
    { role: 'assistant', content: resp.content },
    { role: 'user',      content: results }];
}
afterdeclarative · same weather-bot, described
weather-bot.yaml
# With agntz — the runtime owns the loop.
id: weather-bot
kind: llm

model:
  provider: anthropic
  name: claude-sonnet-4-6

instruction: |
  You are a friendly weather assistant.
  When asked about a city, look up the
  forecast and reply in plain language.

tools:
  - kind: http
    name: get_forecast
    description: Current weather for a coordinate.
    url: "https://api.open-meteo.com/v1/forecast?latitude={latitude}&longitude={longitude}&current_weather={current_weather?}"
    method: GET
$client.agents.run({...})// that's the whole loop
The loop

Edit YAML. Run. Done.

Your agent definition is a file. Change it, version it, deploy it like any other config. No framework migration. No glue code between iterations.

1
step 01Define

Write the YAML.

One file describes the model, instruction, tools, and auth. Lives in your repo next to everything else you ship.

id: support-agent
kind: llm
model:
  name: claude-sonnet-4-6
tools: [...]
2
step 02Run

One call.

Hand the runtime an agent id and an input. It drives the loop — tool calls, retries, context windowing, sessions.

const { output } =
  await client.agents.run({
    agentId: 'support-agent',
    input: '...',
  });
3
step 03Iterate

Edit. Re-run.

Tweak the YAML, commit it, ship it. Agents review in PRs and deploy with the rest of your config.

$ git diff support-agent.yaml
- temperature: 0.7
+ temperature: 0.3
$ git commit -m 'tune'
Agents are config, not code. They live in git, review in PRs, and deploy with your stack — or skip the file and build them in the hosted UI.See the visual builder →
What the runtime handles

The hard parts,
done.

Everything the runtime handles so you don't have to build, test, and maintain it. Shipped in v1.0. Items marked planned are next.

01
shipped

Agent loop

Tool calling, multi-step reasoning, automatic retries on transient failure. You don't write the while-loop.

Learn about the agent loop
02
shipped

Sessions

Resumable across processes. Multimodal input. Reply to any past session — state is durable, not in-memory.

Learn about sessions
03
shipped

Tools

MCP servers, HTTP APIs, and local TypeScript functions — declared the same way. OAuth2, refresh, and credential redaction included.

Learn about tools
04
shipped

Context management

Windowing and summarization handled by the runtime. Long sessions don't blow past the model's context.

Learn about context
05
shipped

Tracing

Every step, every tool call, every token — captured. JSON locally; full timeline UI in hosted.

Learn about tracing
06
planned

Evals

Planned first-class eval records with reusable datasets, async runs, and version comparisons.

shipped= in @agntz/sdk@2.0.0.planned= on the near-term roadmap, tracked in the public changelog.
Run it your way

Same engine.
Three ways to run it.

The runner is production-grade on day one. Pick where it lives based on how your team works — your YAML is the same in all three.

local

@agntz/sdk

Embed it in your Node app.

Embed in any service or worker
Version YAML in git, like config
Bring your own infra and storage
Trace JSON locally, no UI required
$npm i @agntz/sdk
best for
Solo devs, internal tools, existing services.Read the runner docs
hosted

agntz.co

Skip the operations.

Visual agent builder + version history
Managed tracing, sessions, and planned evals
Team collaboration & access control
Auto-scaled, monitored, backed up
$Sign up at agntz.co
best for
Teams iterating fast on shared agents.Open the hosted app
self-hosted

agntz on your infra

Same UI, your perimeter.

Same hosted experience, your stack
Postgres + S3-compatible storage
SOC2-friendly deployment patterns
Full data control, no egress
$docker compose up
best for
Regulated environments, on-prem, air-gapped.Read the self-host guide
Hosted spotlight

Iterate
without rewrites.

When you're ready for collaboration, versioning, and visual debugging — your YAML moves with you, unchanged. Same agent file, same runtime, more surface.

agntz.co agent builder showing the Nutritionist Agent in the Build view
See hosted Free tier · no credit card · same YAML works locally.
Self-hosted spotlight

Run the platform
yourself.

Same Docker image, same features, your infrastructure. No vendor lock-in. No data leaving your perimeter.

requirements
Postgres 14+agent + session store
Node 20+runner + control plane
S3-compatible blobtrace & artifact storage
Docker · Kubernetesdeploy pattern of your choice
~/agntz / docker-compose.yml
4 services
# docker-compose.yml
services:
  runner:
    image: agntz/runner:1.0.0
    depends_on: [postgres, blob]
    environment:
      - DATABASE_URL=postgres://agntz:****@postgres/agntz
      - BLOB_URL=s3://agntz?endpoint=http://blob:9000
    ports: ["3000:3000"]

  control:
    image: agntz/control:1.0.0
    depends_on: [postgres]
    ports: ["3001:3001"]

  postgres:
    image: postgres:14
    volumes: [./data/pg:/var/lib/postgresql/data]

  blob:
    image: minio/minio
    command: server /data
    volumes: [./data/blob:/data]
$docker compose up -d
all healthy
serviceimageportupstatus
runner
agntz/runner:1.0.0:30002d 14h
running
control
agntz/control:1.0.0:30012d 14h
running
postgres
postgres:14:54322d 14h
running
blob
minio/minio:90002d 14h
running

Ship your first agent
today.

Install the runner. Write a YAML file. Call run. That's it.

$npm install@agntz/sdkcopy
from zero to traced run
1. install
npm i @agntz/sdk
2. define
echo 'id: hello' > agents/hello.yaml
3. run
client.agents.run({ agentId: 'hello' })

The whole loop is the runtime's job. Yours is the YAML.