Contract-first API development for coding agents

Define the executable contract first.Let AI build until every promise passes.

Humans approve the behavior. Agents implement, run, and repair until 100% of the contract is green. The same contracts stay in Git and protect every future change, refactor, and rewrite.

  1. Design contract
  2. Implements + repairs
  3. 100% of contract passes

Get started

$npx skills add glubean/skill
Read the docsAsk ChatGPT everything about Glubean

One SDK. One execution model.

Contracts, workflows, custom tests, and load tests.

Define executable contracts across HTTP, Browser, GraphQL, and gRPC, compose them into business workflows, drop to TypeScript for custom checks, and add performance gates. Everything runs on the same engine and can be executed or debugged through the CLI, MCP, or VS Code extension.

contract.http.with()

Cover every input boundary

01

Start with HTTP, then add first-party Browser, GraphQL, and gRPC plugins—every contract stays executable and produces the same structured evidence.

contracts/projects.contract.ts
import { contract } from "@glubean/sdk";
import { api } from "./configure.ts";
import {
  CreateProject,
  Project,
  ValidationError,
} from "./schemas.ts";

const projects = contract.http.with("projects", {
  client: api,
  security: "bearer",
});

// @contract
export const createProject = projects("create-project", {
  endpoint: "POST /projects",
  description: "Create a project with a required name.",
  request: CreateProject,
  cases: {
    created: {
      description: "A valid name creates a project.",
      body: { name: "Payments API" },
      expect: { status: 201, schema: Project },
    },
    nameEmpty: {
      description: "An empty name is rejected.",
      body: { name: "" },
      expect: { status: 422, schema: ValidationError },
    },
    nameTooLong: {
      description: "Names over 80 characters are rejected.",
      body: { name: "x".repeat(81) },
      expect: { status: 422, schema: ValidationError },
    },
    nameMissing: {
      description: "The required name field cannot be omitted.",
      body: {},
      expect: { status: 422, schema: ValidationError },
    },
  },
});
4 executable cases · 1 success · 3 validation boundaries

workflow()

Connect real business journeys

02

Compose existing contract cases into lifecycles where state passes explicitly from one API call to the next.

workflows/order.workflow.ts
import { workflow } from "@glubean/sdk";
import { createCart, checkout, refund } from "./shop.contract.ts";

export const orderLifecycle = workflow({
  id: "order-lifecycle",
  name: "Checkout and refund",
})
  .call("create-cart", createCart.case("success"), {
    out: (_state, res) => ({ cartId: res.body.id }),
  })
  .call("checkout", checkout.case("success"), {
    in: (state) => ({ cartId: state.cartId }),
    out: (state, res) => ({ ...state, orderId: res.body.id }),
  })
  .call("refund", refund.case("success"), {
    in: (state) => ({ orderId: state.orderId }),
  });
Named steps · lifecycle trace · shared state

test()

Check anything with TypeScript

03

Use the imperative API for diagnostics, setup-heavy checks, unusual protocols, and behavior that should stay custom.

tests/health.test.ts
import { test } from "@glubean/sdk";
import { api } from "./configure.ts";

export const health = test("service-health", async (ctx) => {
  const response = await api.get("health");

  ctx.expect(response).toHaveStatus(200);

  const body = await response.json<{ ready: boolean }>();
  ctx.assert(body.ready, "Service is ready", {
    actual: body.ready,
    expected: true,
  });
});
Requests · assertions · diagnostics · traces

loadRunner()

Measure behavior under pressure

04

Run repeatable concurrent scenarios and turn latency, throughput, and error rate into explicit pass/fail gates.

load/catalog.load.ts
import { loadRunner, loadScenario } from "@glubean/sdk/load";

const browse = loadScenario("browse-catalog")
  .step("list products", async (ctx) => {
    const response = await ctx.http.get("products");
    ctx.expect(response).toHaveStatus(200);
  });

export const catalogLoad = loadRunner("catalog-load", {
  scenario: browse,
  concurrency: 25,
  duration: "20s",
  thresholds: {
    transaction: { p95: "<400ms", errorRate: "<1%" },
  },
});
p95 · throughput · error rate · SLA gates

Contract survives implementation

Define the promise once. Make every future implementation prove it again.

Start from agreed behavior—or recover it from an API you already have. Either way, the executable contract stays in Git while humans and agents replace the implementation around it.

Primary loop · Contract-driven

Agree on behavior before the agent implements it.

Turn product intent into an executable contract first. Once a human confirms it, the agent implements or repairs the API until the live behavior satisfies that contract.

After confirmation, fix the implementation—not the contract. Every green contract stays as the regression suite and shared design memory.

01

Clarify intent

02

Write contract

03

Human confirms

04

Implement API

05

Run + prove

Durable design memory

The implementation changes. The confirmed contract stays.

The same executable promise remains in Git and reruns against every future version of the API.

Illustrative history · replace with real project data

contracts/projects.contract.ts

projects · create-project.* · 4 executable cases

contract unchanged
commitimplementationsrc diffcontract diffresult
c19e4btodayHuman implementation+126 −00✓ 4/4
7a4fd2+8 weeksAgent rewrite+184 −1670✓ 4/4
e83b11+6 monthsService refactor+92 −1140✓ 4/4

Addressable evidence

Every event is born with an address.

The runner knows the contract, case, target, and run before the first event is emitted. It attaches that identity to requests, responses, assertions, traces, screenshots, and metrics as they happen—not by trying to reconstruct it from logs later.

Runner-level capture

Capture and identity happen together.

Because the runner owns the execution context, every event inherits stable keys automatically. More print statements cannot create a primary key that was never recorded.

contractprojects
casecreate-project.created
targetstaging
runrun_145
00.000
case.startedcreate-project.created
00.014
http.requestPOST /projects
00.182
http.response201 Created
00.185
assert.passedstatus = 201
00.187
trace.attachedrequest + response

Identity attached at capture · not inferred after the run

Cross-run join

Stable keys join runs into history.

Each run gets a new run ID while preserving the same contract, case, and target identity. That is what makes results comparable across time.

projects / create-project.created / stagingstable keyflaky
runresultduration
run_141passed · 201186ms
run_142failed · 409191ms
run_143passed · 201182ms
run_144failed · 409194ms
run_145passed · 201177ms

Accumulate these stable IDs in Glubean Cloud to unlock regression history, flaky detection, health reports, and performance trends.

What you get

Adopt one SDK. Keep one verification system.

Glubean turns separate testing tasks into a shared body of API knowledge that compounds with every useful run.

01

One verification project

Keep endpoint promises, business journeys, custom checks, and performance plans together in versioned TypeScript.

02

One execution model

Run the same source locally and in CI. Keep evidence on the machine or upload meaningful runs to Cloud.

03

One evidence trail

Humans and agents inspect the same requests, responses, assertions, traces, diffs, and performance history.

Shared history in Cloud

Keep the runs that should outlive a terminal.

Execution stays local-first. Upload selected runs when your team needs stable history across machines and CI: target health, contract drift, run diffs, flaky detection, and performance trends in one place.

Explore Glubean Cloud
app.glubean.com · target overview
Glubean target overview showing run and performance evidence
01

Execute

Run locally and in CI.

The runner produces complete evidence for each run. Keep it on the machine or as a CI artifact—no account required.

02

Retain

Upload only the runs worth keeping.

Glubean Cloud preserves the same identities across branches, machines, and CI so shared history can accumulate over time.

What retained history unlocks

Runner-created identity, accumulated by Cloud.

01

Regression history

See which contract cases changed from green to red.

02

Flaky detection

Identify inconsistent cases across repeated runs.

03

Health reports

Summarize target and endpoint reliability over time.

04

Performance trends

Track latency, throughput, and SLA movement.

Local first, no lock-in

Your code runs before your account exists.

Open source SDK. Plain TypeScript. Run on a laptop or in any CI. Secrets stay local, and redaction runs before evidence uploads.

~/api-verification
$ glubean run
 contracts · 12 cases passed
 workflows · 3 lifecycles passed
 tests · 8 checks passed
 load · p95 182ms · thresholds passed

Start with one executable contract.

Install the Glubean skill. Your coding agent can inspect the repo, define the contract with you, and run it against the real API.