Skip to content

Changelog ​

Unreleased ​

  • gateway: a first message no domain claims no longer locks the chat to the first domain. The router held a chat in its domain as soon as the session had a draft, and the step engine creates an empty draft (steps: {}) on the first turn of every domain, so hello there (no keyword hit, the first domain answered) kept every later message there, a ticket opener included. ADR-0001 says sticky means never re-route mid-journey or after completion; now the chat is held when it finished, when a link decided its domain (session.domainDecided), or when the journey has begun (something gathered, a step with state, the summary or a review up: route-lock.ts). A chat that only fell back is classified again, with the active domain's stickiness bias, and its empty draft is dropped when it moves. evals: the bookings suite gains greeting-then-opener (red on main) and sticky-mid-journey (the lock the fix keeps).
  • gateway, core: the dev trace. With AGENT_DEV_TRACE=true (default off; .env.example sets it, render.yaml and .env.production.example leave it off) every turn carries what the gateway already logged, as a client payload: the route decision (the domain, the link that decided — keywords, systemone, llm, sticky, single, fallback — and its confidence), the step engine's events (drawn, late_draw, redrawn, reopened, settled, skipped, summary), every tool call with the arguments it received (after the carry rule) and its result (masked, clipped), and each model call's time and tokens. It rides the SSE done event and the JSON reply as trace; the last 30 turns are kept on the session and GET /api/session/:id/history replays them as turns, so a reload can rebuild the Trace pane. GET /api/health reports dev_trace. Nothing new reaches telemetry: spans, metrics and behaviour events keep their counts and enums. Shape: docs/CLIENT-PROTOCOL.md, "The dev trace".
  • playground: the Trace pane draws the dev trace per turn: the route with its confidence, the step events as a line (asked, redrawn, settled, summary shown), each tool call folded with its arguments and result, the model's calls and timings; a gateway without the flag keeps the old view plus a note saying why. A reload rebuilds both panes from the one /history response: the Draft pane from preview (a finished chat came back empty before: the widget clears the preview when a chat completes) and the Trace pane from turns. The usage pill read input_tokens/plan_tokens and never showed; it reads turn_tokens/turn_plan, which the gateway sends. The phone layout is unchanged.
  • widget: onTurn gains trace (null when the gateway sends none) and a new onHistory(history) hook hands a host the whole /history response when a chat is resumed or opened. Both are additive; the fake-DOM tests cover them.
  • evals: TurnResult gains trace and turns; the checks hasTrace, routeIs, stepEvent, toolCall and reloadKeepsTrace. The support-intake dev-trace scenario walks the journey with them (the route and its confidence, search_customers with its query and the two matches, Details asked → redrawn → settled, the create refused with writes off, and the same facts after a reload); the bookings routing scenarios assert the route both ways. npm run gateway:evals sets the flag.
  • core: the review no longer draws the summary over an answer the change made stale. After "Change something" → a section → a changed answer, the steps that dependsOn it were reset, but the settle called drawSummary() directly, so nextOwed() was never asked: the card came back at once still showing the old Priority, a typed yes was a go-ahead, and the ticket was written with the tool's default (medium) while the user had confirmed high. The edit settle now goes through the same chain as every other settle: the reset step is asked again (with one line saying why) and the summary returns after it. Found by walking the example by hand while building a new domain on 0.3.0. A reset now counts as behaviour_events_total{kind="step",type="reset"}, is a log trace line, and a reset event in the dev trace (the Trace pane says it). The create gate is untouched in all three layers. evals: cardRow(key, { value }) checks a drawn summary's field; the example suite gains review-edit-reasks-dependent (red on the old engine at the turn the summary returns, and at the typed yes that reached the write tool) and review-edit-unchanged (an unchanged edit asks nothing again). check:e2e now also drives the review path with writes on and asserts the record on disk is the summary that was confirmed (red on the old engine).

0.3.0 — 2026-10-14 ​

The release the site already describes: tools in Python, simulated users in the evals, an English reader core with opt-in registers; plus what the 0.3 review's walk as a stranger found and fixed.

  • core: a partial form submit is drawn again pre-filled and with the missing or invalid rows marked. The redraw's state (pending values, per-row errors, a multi-pick's picks so far) reached the stored step only after the draw, so the card came back empty; the playground showed it. evals: formRow(key, { value, error }) checks a drawn form's row; the example's partial-redraw scenario now asserts the pre-fill and the mark (red on the old engine).
  • cli: marg web | new | evals | check refuse a flag they do not know (exit 2, the help printed) instead of ignoring it: an older marg new … --lang python scaffolded a TypeScript server and said nothing. marg new fails when the templates lack the server template for the chosen language; marg --version prints the version; marg verdict --help reaches Verdict.
  • playground: the empty state skips a domain's example openers that are still the template's placeholders (<verbatim thing a user would type>), so a freshly scaffolded domain does not offer them as suggestions.
  • site: /llms.txt — the site's index for coding agents (every page with its title, by section), written by the sync from the same page map as the nav.
  • docs: a review of 0.3 walked as a stranger and set beside Google ADK, the OpenAI Agents SDK, LangGraph and Pydantic AI, area by area, with every gap ranked and classified (docs/reviews/0.3-review-2026-10.md), and ROADMAP "0.4 — what the walk found": the trace pane that shows what the gateway knows and survives a reload, a model-played user, the since line and the live version on the site, the skill installable in one line.
  • templates: a Python tool server. npm run new-domain -- <name> --lang python (and marg new … --lang python) writes mcp/server.py on the official mcp SDK (2.x, MCPServer over stdio) and mcp/requirements.txt, with the same tools and contracts as the TypeScript server: the validate / preview / create triad, the bearer in _meta["agent/auth"], the session id and the W3C trace context in _meta, the write gate, JSON lines to stderr. The manifest points python3 at it. SCAFFOLD_LANG=python npm run check:scaffold proves it; CI runs that on Python 3.11. Guide: docs/guides/python-tools.md.
  • core: the readers' vocabulary is English; Hindi and Hinglish are an opt-in lexicon. reply-words.ts keeps the English sets and rewrites; every Hindi and Hinglish word, rewrite, question marker and skip phrase lives in lexicons/hinglish.ts, loaded with AGENT_LEXICONS=hinglish (the gateway logs what it loaded) or loadLexicons(["hinglish"]). extendLexicon takes rewrites, question openers and leads, cut-offs, unfinished tails, question exceptions and skip phrases as well as words. The readers guide describes registers.
  • evals: simulated users — a scenario may set user instead of a turn list; the runner asks it for each next message from a view of the conversation until it returns null; everyTurn checks apply to every turn; cooperativeUser plays a deterministic persona (an opener, answers for form rows, preferred taps, asides on cue, stops on completion or a refused write). One simulated-user scenario in each example suite runs in CI on the mock model.

0.2.1 — 2026-10-14 ​

The first release published by CI through npm trusted publishing (OIDC, provenance generated by npm); 0.2.0 went out by hand. No runtime changes beyond the CLI package's name.

  • cli: the package is @marg-adk/cli (npm refuses the bare name marg as too similar to existing packages); the command is still marg. bin paths no longer start with ./, which npm 11 rewrote on publish.
  • release: npm publishing by trusted publishing (OIDC, no token, provenance automatic); scripts/publish-first.sh for a package's first version by hand; RELEASING.md describes the one-time setup per package.

0.2.0 — 2026-10-14 ​

The adoption release: installable from npm, a site, a playground that is also the dev UI, one command, a method for coding agents, a second example, every model provider, and the pipelines of a public repository.

  • models: presets for every provider a developer is likely to meet — Vertex AI, Azure OpenAI (the api-key header), Bedrock, LiteLLM, xAI, Cohere, Hugging Face, Cerebras, Perplexity, NVIDIA — beside the existing OpenAI, Gemini, Ollama, vLLM, Groq, Mistral, DeepSeek, Fireworks, Together, OpenRouter and the native Anthropic adapter; gen_ai.provider.name follows the semantic conventions for the new ones; a unit test resolves every preset from the environment.
  • docs: docs/providers/ (one page per model provider, with the env lines; Gemma, gateways such as Apigee, on-device runtimes explained) and docs/integrations/ (observability backends over OTLP — Langfuse, Datadog, Grafana Cloud, Honeycomb, Phoenix, SigNoz, New Relic, Jaeger — stores, speech, decisions, MCP tools, other frameworks, hosting, coding agents); both are sections on the site.
  • skill: skills/build-a-domain/SKILL.md, the method for building a domain as a skill a coding agent follows (the worksheet, the build order, the gate, the classification rule, the never-rules); Claude Code loads it from .claude/skills, AGENTS.md points other agents at it, create-marg-app installs it in new projects, and the site shows it under Build.
  • example: examples/bookings, the second domain, built by following the build-a-domain skill: a venue picker, a Details card with a date row, a bespoke Time step fed by an availability tool (the no-availability path offers the nearest days and moves the date), its own mock policy and nine scenarios including routing to each domain (npm run evals:bookings, in CI).
  • core: a date form row kind (an ISO day; the widget draws a date input; isIsoDay); the mock model registry is per domain (registerMockModel(fn, domain)), and the agent names its domain on every model call, so two example domains share one gateway; a utility hop with no domain gets an empty mock answer. evals: TurnResult.domain and the inDomain(name) check.
  • repository: CI fails when a generated path (the site's mirrored docs or build, a package's dist/ or payload) is tracked; Dependabot ignores major bumps of @types/node (the engine is Node 22).
  • site: https://marg-adk.github.io/marg — VitePress on GitHub Pages, built from the repository's docs on every merge (website/, npm run site:build): a landing page, Get started · Build · Components · Run · Reference · Community, search, a comparison page, an FAQ. Pull requests build it, so a dead link fails the PR.
  • marg: the marg command on npm — web (the gateway and the playground), new (a domain from the templates), evals (every suite against a writes-off gateway), verdict (a typed decision from the shell), check (the project's gate: typecheck, then every suite with writes off on its own gateway). create-marg-app wires it into a new project's scripts; check:create runs marg check in the created project.
  • docs: a review of adk.dev and what Marg takes from it (docs/reviews/), and ROADMAP "0.3 — the surface": the site, the playground as the dev UI, a marg CLI, a skill for coding agents, provider pages, user simulation.
  • playground: redesigned as the dev UI — a plain top bar with the model and writes status, one centred conversation, the live draft and a new trace pane (per turn: runtime or model, every tool call with its time, usage, the create) as side panels that collapse, past chats in a drawer, the domains' example openers on the empty state, usable on a phone. The README GIF is re-recorded on it.
  • widget: header: false for host pages with their own chrome; onTurn(turn) hands the host every completed turn's facts (domain, kind, tool trace, usage, completion); bubbles hug their text. /api/health lists each domain's example openers.
  • deploy: the image ships tsconfig.base.json (without it tsx lost the path mappings and the gateway crashed at boot — the first Render deploy failed on this); CI now builds the image and probes its health, playground and widget (image job, required).
  • docs: the launch post, docs/posts/the-model-must-never-read-yes.md (the long form, the Show HN comment, the r/LLMDevs post, the thread), linked from the README.
  • docs: the README opens with docs/images/playground.gif, the six-turn journey recorded from the playground on the mock model (0.14 MB).
  • playground: render.yaml, a Render Blueprint for the hosted playground (mock model, writes off, no login, rate limits on), deployed at https://marg-playground.onrender.com and linked from the README.
  • core: the form-reply pair parser scans instead of matching a regex that backtracked polynomially on long runs of spaces in user text (CodeQL, high). The Docker healthcheck and the CI gate poll /api/health, the path the gateway serves.
  • repository: the gate runs on Node 22 and 24 with npm run lint (ESLint, correctness rules only) first; CodeQL, a security workflow (dependency review, npm audit; GitHub secret scanning with push protection on the repository) and the OpenSSF Scorecard run on every PR or weekly; Dependabot keeps npm and Actions current in grouped weekly PRs; CODEOWNERS, issue templates (bug, feature, domain request), a pull-request template that asks for the gate output and a classification of every red, RELEASING.md, .nvmrc, .editorconfig, and badges in the README.
  • packages: every package is publishable — a build per package (tsc -p tsconfig.build.json to dist/, ESM + .d.ts), exports, types, files, publishConfig.access: public; @marg-adk/widget is now a package (the file plus a manifest); @marg-adk/gateway ships a marg-gateway command that registers the tsx loader and runs the compiled server. The tsx development path through tsconfig.json paths is unchanged.
  • create-marg-app: npx create-marg-app my-agent copies the templates, the example domain, the shared skills and the scaffolder into a fresh project depending on the published packages.
  • core: when installed from npm the project root is the working directory (walking up to the nearest package.json or .git), so .env, domains/, examples/ and shared-skills/ are found in the user's project; AGENT_REPO_ROOT still overrides.
  • gateway: the playground page and the widget are located relative to their packages, not the repository; /api/skills honours AGENT_SHARED_SKILLS_DIR.
  • checks: check:pack (every package packs clean) and check:create (a project from local tarballs installs, boots and passes the example suite); a packages CI job runs both.
  • release: a tag v* runs the gate and publishes every package with provenance (with a token at the time; trusted publishing since — see Unreleased).

0.1.0 — 2026-10-13 ​

First open-source release, extracted and generalised from a production agent.

  • core: the domain-agnostic runtime — prompt assembly from markdown skills (typed variants, capabilities, security preamble), the model chain (Anthropic, any OpenAI-compatible endpoint, a scripted mock) with failover, breaker, retries and per-endpoint configuration, MCP tools with reconnect and hidden internal_* tools, sessions with bounded memory and healed history windows, durable stores with fallback, two-stage tool-output trimming, runtime-owned steps (draw / read / settle / chain / late draw / redraw / review / carry / dependencies / reload redraw), whole-content readers, the create gate and attested-list guard, tolerant ui-block parsing and sanitising, OpenTelemetry seam, structured logs off the main thread.
  • verdict: typed decisions (choice / noul / score) with rules, System One (Laya / any compatible server), LLM logprobs and mock backends; a cascade; calibration maths; a CLI, an MCP server and a System One-compatible HTTP server.
  • gateway: HTTP + SSE; sessions with verified identity and owner checks; the agent-token exchange; rate limits with runtime-turn refunds; usage caps in plan tokens shown as percentages; media (upload ≠ attach); voice (Deepgram or any Whisper-compatible endpoint); nudges; health, metrics, HTTP tracing; a metering sink; graceful shutdown.
  • evals: the scenario runner with sharding, reruns, flake classification and a gate report.
  • widget: streaming, chips, multichips, lists, cards with sections, toggles, forms with echoes, tables, progress, media, bars; resume, nudges, voice, uploads; link scheme allowlist.
  • example: support ticket intake, end to end offline with a scripted mock model; 7 scenarios.
  • checks: check:otel (the telemetry seam against in-memory exporters and a stub log sink), check:scaffold (the templates produce a domain that compiles and passes its own suite), check:e2e (the real write path with writes on); the widget driven under a fake DOM in tests.
  • observability: Docker Compose for OpenObserve (+ optional collector), generated dashboards and alerts (o2:dashboards), an idempotent o2:bootstrap.
  • deploy: a non-root Dockerfile with a health check, Compose profiles (stores, observability, decisions with Ollama + laya, edge with Caddy), a production env example, DEPLOY.md; a CI workflow.
  • docs: the pattern, the lessons, the playbook, the production checklist, the client protocol, decisions, observability, metering, security, the auth design, six ADRs, guides, templates.

Source: CHANGELOG.md — edit it there; the site mirrors the repository.

Apache-2.0. The docs are mirrored from the repository on every merge.