GNL 0.17: early and moving fast — APIs can change between releasesJoin us

GNL
Core · Free@gnldev/durable

Start with the core. Take the rest when you need it.

GNL is a full agent framework, durable from the core. You can use all of it, or put only the core into an agent you already have — and go from one to the other a step at a time.

Five steps, none of them a rewrite#

Each step keeps what the one before gave you and adds to it. Stop at any of them.

  1. The core — runDurable instead of generateText: a tool call is never fired twice, and a crashed run resumes where it stopped.
  2. A registry — createGnl: agents by name, work named by your own id (workKey), runs that outlive the call that started them, approvals.
  3. A server — createRestApi: REST, OpenAPI and server-sent events for every agent, with auth, limits and budgets.
  4. Studio — every run on a timeline, time-travel and fork, the approval queue, a playground.
  5. The packages — memory, workflows, RAG, evals, MCP, jobs, channels: each one carries the core's guarantees.

1. The core, inside the agent you already have#

The arguments are generateText's. The additions are an id for this piece of work and a journal in your own database.

agent.ts
import { runDurable, gnlTool } from '@gnldev/durable';
import { SqliteStorage } from '@gnldev/durable/sqlite';
import { openai } from '@ai-sdk/openai';
import { tool } from 'ai';
import { z } from 'zod';

const storage = new SqliteStorage('runs.db');

const refund = gnlTool(
  tool({
    description: 'Refund an order',
    inputSchema: z.object({ orderId: z.string() }),
    execute: async ({ orderId }) => ({ refunded: orderId }),
  }),
  { sideEffect: true, idempotency: 'args' },
);

const res = await runDurable({
  runId: 'refund-order-42',          // the id of THIS work — call again with it after a crash
  journal: storage.runs,
  model: openai('gpt-4o'),
  tools: { refund },
  prompt: 'Refund order 42',
});

Call it again with the same id after a crash: finished steps replay from the journal, the refund is not issued a second time, and only what never finished runs.

2. A registry: agents by name, work by your id#

Name the agent once and each piece of work with your own id — an order, a ticket — and the engine derives the run from it. A run now executes apart from the call that started it: a closed tab or a dropped connection ends the reading, not the run.

gnl.config.ts
import { createGnl } from '@gnldev/durable';

const config = {
  storage,
  agents: {
    support: { model: openai('gpt-4o'), system: 'You handle refunds. Ask before you refund.', tools: { refund } },
  },
};
const gnl = createGnl(config);

const r = await gnl.run('support', { workKey: 'order-42', prompt: 'Refund order 42', resourceId: 'customer-7' });

3. A server: every agent over HTTP#

The same config becomes a REST API with OpenAPI and server-sent events. In production it refuses to start without auth.

server.ts
import { createRestApi } from '@gnldev/server';
import { roleAuth } from '@gnldev/auth';
import { serve } from '@hono/node-server';

const api = createRestApi(config, {
  title: 'Support agents',
  auth: roleAuth({ client: { token: process.env.GNL_CLIENT_TOKEN } }),
});
serve({ fetch: api.fetch, port: 3000 }); // POST /agents/support/run, /agents/support/stream, /openapi.json

On Express, Fastify, Koa, Nest or Next.js: the REST API page.

4. Studio: watch, approve, go back in time#

Studio reads the same journal: every run on a timeline, the calls waiting for approval, time-travel and fork, and a playground that runs the agents in your config.

npx gnl studio --config gnl.config.ts   # Studio + the playground for the agents in your config

5. The packages: take what you need#

Each package works with the rest and on its own, and a tool or a step it adds is journaled like the core's — replayed after a crash, never fired twice.

Tip
Starting from nothing instead? npm create gnl@latest my-agent sets up steps 2 to 4 in one go.

Sources#

The samples on this page are typechecked against the packages as built, in the repository: docs/CORE-TO-FRAMEWORK.md