Run a B2B quote approval workflow: from client brief to audit receipt

2026-09-07 · edited by Aetha Editorial

A customer asks for 25% off. Your CRM needs to calculate the proposal, hold it for approval and retain the decision. This worked example takes a short client brief through that process using Accordo's existing commercial package.

Download the client brief, then run the example below. It creates a local project you can inspect. The recorded execution includes the result and the setup mistake corrected during development.

See the recorded result

The short recording inspects the completed synthetic replay: the approved quote, its decision and the real audit API response. It does not show an authenticated human session or a coding agent building an application.

The customer request

Northwind Studio is a synthetic customer buying 30 seats of the fixture Enterprise Plan. Its catalog has a EUR 5,000 setup charge, a EUR 2,000 monthly platform charge and EUR 40 per seat per month at this quantity. The requested 25% discount applies to each component.

The existing policy auto-approves discounts through 10%, requests a user decision above 10% through 50%, and rejects larger discounts. These are the example's rules and prices, not Accordo subscription pricing. Both are defined in the starter catalog and policy.

Run the exact workflow

Use Git, Node.js 22.16 or newer and npm. Start in an empty working directory with internet access for the checkout and dependency installation:

git clone https://github.com/khaoss85/agent-crm.git framework-source
cd framework-source
git checkout 3b5b5f0c4c3e582e48d54501136024b064756daa
git rev-parse HEAD
node --no-warnings examples/recipes/quote-approval/run.mjs ../my-quote-crm

The recipe source uses the scaffolder in that checkout, installs the generated project's dependencies, composes the commercial modules and starts a temporary HTTP server on localhost. It drives the public SDK and closes the server when finished. It does not use the npm scaffolder release.

The receipt records the checkout commit and recipe hash. Keep that commit to reproduce a saved run. Choose a new target directory for another replay: the scaffolder refuses an occupied project.

What the execution checks

The server calculates EUR 3,750 once and EUR 2,400 per month after discount. It keeps those periods separate. Submission freezes the commercial snapshot under policy version 1 and places the quote in pending_approval.

The simulated agent then tries to approve:

Agent approval refused: 403 HUMAN_APPROVAL_REQUIRED. Quote and approval remain pending; no business audit added.

The recipe asserts that refusal and unchanged business state, then calls the same action as a simulated user. It checks an approved decision, exactly one user decision audit, and an unchanged submitted snapshot. It also reads the failed agent trace and the completed user trace. These assertions extend the worked example around the already tested commercial approval behavior.

Both actors are scripted local identities. Nobody authenticates or clicks Approve during this replay. A production deployment must supply a verified identity and authorization configuration; the example's sales-manager approval key is a label, not a login role.

Inspect what remains

cd ../my-quote-crm
cat data/quote-approval-receipt.json
npm run verify
npm run crm -- app inspect --json

The local SQLite database and JSON receipt remain in data/. The receipt connects the quote, frozen version, policy fingerprint, approval, decision audit and traces. Project verification checks technical health; the recipe's assertions check this particular business journey. The audit records what the process did under the asserted actor; it is not an externally attestable compliance log.

The mistake the first run caught

The first implementation generated commercial modules alphabetically. A reference to the quote table failed because the quote module had not been installed yet. Using the dependency order from the existing commercial test corrected the setup, and the recorded execution then passed. The generated project also initially retained a starter test expecting no domain packages; the recipe now changes that assertion to require the commercial package. Both findings stay in the transcript's development history.

This is a deterministic replay of existing primitives. It does not measure Claude Code or Codex building a CRM from a prompt, and it establishes no build success rate. The catalog is a fixture; no email, signature, billing or customer notification is sent. The evidence ledger gives the wider product boundaries.

Try your own brief next

Use the downloadable brief as a starting point. Replace the sample customer process, then ask your coding agent to inspect the project and propose the smallest reviewed change. Keep the price checks, refusal and audit checks as acceptance criteria. That adaptation is a separate build to evaluate; this example does not claim it has already succeeded.

What this post does not mean

These pages describe this repository at this commit. None of them implies the framework is deployable, and none of them is a roadmap: nothing that is not merged appears on this site, in any tense.

  • No authentication ships: the framework authenticates nobody. Production Spine v1 (ADR-038) gives the framework verified identity, organizations and memberships, server-authoritative authorization and one tenant per application instance — so tenancy and authorization now exist and are enforced. What does not exist is authentication: no login, password, session or OIDC implementation ships, and a deployment must supply the adapter that verifies the request. Production mode refuses to start without one. In local-development mode an actor header is accepted as an assertion and is not an identity, which is the default developer posture. This is not shared-database multi-tenancy and it is not a readiness claim.
  • Not shared-database tenancy. createAccordoAppAsync can boot one tenant onto dedicated PostgreSQL databases. Shared-database row-level tenancy is not implemented, and this is not a production-readiness claim.
  • Timers exist; a service that runs them for you does not. Durable jobs, a transactional outbox and scheduled asks exist for self-hosted applications that explicitly start a worker. Nothing autostarts; a timer opens an ask, never makes a decision, and no managed worker service or recurrence is included.
  • No email, calendar or marketing integrations. An in-memory notification provider contract exists. No adapter sends anything to anyone.
  • The build benchmark has not been run. The protocol is designed and published; no Successful Agent Build Rate exists yet. Any number you see quoted for this project is not ours.
  • Ownership means vendored source: there is no framework dependency to bump. The published create-accordo@0.1.0 scaffolds vendored source; it is the August 19 snapshot, not the current repository feature set. Use a current source checkout for the capabilities described here; upgrades require merging source (L-08). The framework is copied into the project, not installed as a framework library dependency. The accordo npm name is an empty reservation; the @accordo scope is claimed and deliberately empty.

Every claim and every limitation is on one page, and the questions this project refuses to answer are published beside them.

The evidence this post rests on

Claims

  • C-04 The agent cannot approve on the human's behalf. A test asserts the refusal, so the boundary is a property of the system rather than a promise in a README.

    LimitIn local-development mode the actor is asserted, not authenticated: no authentication ships, so an actor header there is not an identity. This holds a boundary against an honest agent, not against an attacker with network access.

  • C-08 Quotes price on the server from a catalog — one-time and recurring, flat, per-unit, volume and graduated tiers — and freeze into an immutable version when a discount goes for approval.

    LimitCatalog sync runs against a fixture provider; no real external catalog (Stripe, Zuora, ERP) is connected. Money is integer cents with no FX — currencies are never summed.

  • C-16 Every mutation goes through a module service or a named workflow, and leaves an audit event and a step-level trace behind it.

    LimitAudit records what the process did under an asserted actor. It is not a tamper-evident or externally attestable log, and it is not a compliance control.

Grounded in

  • site/assets/recipes/quote-approval-transcript.txt

Editor of record

  • Aetha Editorial