<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Accordo]]></title><description><![CDATA[Accordo]]></description><link>https://accordo.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1593680282896/kNC7E8IR4.png</url><title>Accordo</title><link>https://accordo.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 09 Sep 2026 02:28:42 GMT</lastBuildDate><atom:link href="https://accordo.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Replay a B2B quote approval workflow and inspect its audit receipt]]></title><description><![CDATA[When evaluating a custom CRM, I want to inspect more than its final screen. Which price was calculated? Which policy required review? Did approval change the terms? Can I connect the decision to the q]]></description><link>https://accordo.hashnode.dev/replay-a-b2b-quote-approval-workflow-and-inspect-its-audit-receipt</link><guid isPermaLink="true">https://accordo.hashnode.dev/replay-a-b2b-quote-approval-workflow-and-inspect-its-audit-receipt</guid><category><![CDATA[crm]]></category><category><![CDATA[ai agents]]></category><category><![CDATA[open source]]></category><category><![CDATA[software architecture]]></category><dc:creator><![CDATA[daniele]]></dc:creator><pubDate>Mon, 07 Sep 2026 20:51:49 GMT</pubDate><content:encoded><![CDATA[<p>When evaluating a custom CRM, I want to inspect more than its final screen. Which price was calculated? Which policy required review? Did approval change the terms? Can I connect the decision to the quote it concerned?</p>
<p>This small Accordo example makes those questions concrete. Accordo is an open-source framework coding agents use to build CRM applications as source you own. The example composes its existing commercial package around a synthetic customer request, then leaves the project and receipt on your machine.</p>
<h2>Start with a specific request</h2>
<p>Northwind Studio requests 30 seats of the fixture Enterprise Plan. The catalog charges EUR 5,000 once for setup, EUR 2,000 monthly for the platform, and EUR 40 per seat per month at that quantity. The rep requests 25% off every component.</p>
<p>The policy auto-approves through 10%, requires a user decision above 10% through 50%, and rejects larger discounts. After pricing, the proposal is EUR 3,750 once and EUR 2,400 monthly. They remain separate amounts: adding them together would hide the difference between setup and recurring charges. These are fixture prices, not Accordo subscription pricing.</p>
<h2>Create and run the project</h2>
<p>Use Git, Node.js 22.16 or newer and npm. Start in an empty working directory; cloning and dependency installation need internet access.</p>
<pre><code class="language-sh">git clone https://github.com/khaoss85/agent-crm.git framework-source
cd framework-source
git checkout 3b5b5f0c4c3e582e48d54501136024b064756daa
node --no-warnings examples/recipes/quote-approval/run.mjs ../my-quote-crm
</code></pre>
<p>The recipe installs the generated project's dependencies, opens a temporary localhost server and uses the public SDK over HTTP. It creates the opportunity and quote, submits the discount request, tests the agent refusal, then simulates the user decision. It closes the server afterward. An occupied target directory is refused; use a new one for each replay.</p>
<p>You can read the <a href="https://github.com/khaoss85/agent-crm/blob/3b5b5f0c4c3e582e48d54501136024b064756daa/examples/recipes/quote-approval/run.mjs">complete pinned implementation</a>. No running vendor catalog or npm scaffolder release is required for the business journey.</p>
<h2>Read the decision evidence</h2>
<pre><code class="language-sh">cd ../my-quote-crm
cat data/quote-approval-receipt.json
npm run verify
npm run crm -- app inspect --json
</code></pre>
<p>Follow these fields in the receipt:</p>
<ul>
<li><p><code>totals</code> keeps the one-time and monthly prices separate.</p>
</li>
<li><p><code>agentRefusal</code> records HTTP 403 and <code>HUMAN_APPROVAL_REQUIRED</code>; <code>refusalTrace</code> records the failed attempt.</p>
</li>
<li><p><code>decision</code> contains the approved status, policy version and fingerprint, and simulated reviewer identity.</p>
</li>
<li><p><code>snapshot</code> preserves the submitted commercial terms; the recipe checks that approval leaves it unchanged.</p>
</li>
<li><p><code>humanAudit</code> and <code>approvalTrace</code> connect the user decision to the approval and quote version.</p>
</li>
</ul>
<p>The script checks the intermediate <code>pending_approval</code> state before attempting approval and verifies that refusal leaves the business state unchanged. The receipt describes this one completed replay; project verification and source inspection answer different questions about the generated application.</p>
<p>Both actors are simulated local assertions. This is not authenticated human approval, a coding-agent build session, a benchmark, or production validation. The catalog is a fixture. Deployment identity and authorization configuration need separate work, and an audit record is not an externally attestable compliance log.</p>
<p>The generated project contains source you can inspect and adapt. <a href="https://accordo.dev/blog/run-a-b2b-quote-approval-workflow.html?utm_source=hashnode&amp;utm_medium=syndication&amp;utm_campaign=quote-approval">Download the brief and compare the recorded execution</a> before describing your own process.</p>
<p>We are opening three bounded pilots for teams with a real quote or approval process. To express interest, comment with a synthetic description of the process and the decision that needs a human. Do not post customer data. We will define the scope and acceptance criteria together before work begins.</p>
]]></content:encoded></item><item><title><![CDATA[What our inspector refuses to tell you]]></title><description><![CDATA[Most tools report what they found. Ours also reports what it cannot see — as structured data, in the same JSON document, with stable codes an agent can branch on.
Run npm run crm -- app inspect --json]]></description><link>https://accordo.hashnode.dev/what-our-inspector-refuses-to-tell-you</link><guid isPermaLink="true">https://accordo.hashnode.dev/what-our-inspector-refuses-to-tell-you</guid><dc:creator><![CDATA[daniele]]></dc:creator><pubDate>Thu, 20 Aug 2026 21:41:55 GMT</pubDate><content:encoded><![CDATA[<p>Most tools report what they found. Ours also reports what it cannot see — as structured data, in the same JSON document, with stable codes an agent can branch on.
Run npm run crm -- app inspect --json in this repository and the report describes the composed application from checked-in source: packages, capabilities, resources, actions, policies, providers, modules. Then, before the document ends, it lists eleven limitations[] entries. The run behind this article was made on 2026-08-18 and saved unedited at docs/transcripts/2026-08-18-app-inspect-limitations.json; every quote below is from that file.
Two things in that transcript are worth noticing before the limitations. First, valid is true. Second, the composition is nearly empty — four core modules, no packages, no actions, no providers — because the framework repository itself is not a composed product. The inspector does not pad the answer to look busier: an application that composes nothing is reported as an application that composes nothing, and it is still a valid one.
The eleven refusals
The codes group naturally into what the inspector never opens, what it cannot know, and what it admits about itself.
It never opens your database. DATABASE_NOT_INSPECTED says it plainly: “the configured application database is never opened, so what a particular database has applied, holds or is missing is unknown.” Its sibling SECRETS_NOT_INSPECTED adds that no secret, credential, token or environment value is read, and no provider is contacted. DATA_QUALITY_UNKNOWN closes the set — source-only inspection “can say which records exist, never whether their data is correct, complete or duplicated.”
It refuses to infer runtime state. RUNTIME_STATE_UNKNOWN (“nothing here reports what is running, deployed or reachable”), PROVIDER_HEALTH_UNKNOWN (a registered provider definition means a provider was composed, “never that it is reachable, configured or operational”) and CI_EVIDENCE_NOT_INFERRED (no CI, browser-smoke or benchmark result is read) all guard the same line: a source tree is evidence about source, and pretending otherwise is how a report becomes a rumor.
It refuses to parse prose into claims. EVIDENCE_NOT_AGGREGATED states that JTBD and quality-gate status “live in Markdown maintained by people; they are referenced by path and never parsed into structured claims.” The report’s evidence block carries the paths and a status of not_aggregated rather than a synthesized score.
It names what does not exist anywhere. PRODUCTION_SPINE_ABSENT repeats, inside the machine-readable output, what the composition block already stated as productionPosture: there is no authentication, tenancy or RBAC in this framework, so no runtime authorization can be reported. And ADMIN_EXTENSIONS_UNSUPPORTED makes a distinction most tools skip: adminExtensions is empty “for every project — not merely empty for this one.” An empty array is ambiguous; this code removes the ambiguity in the direction least flattering to the framework.
It confesses its own execution model. The two remaining codes are about the inspector, not the application. PACKAGE_SOURCE_TRUSTED: reading a code-first package means importing it, so “package code runs with this process’s authority. Nothing here is sandboxed.” PROCESS_ISOLATION_BOUNDED: the load runs in its own process group under a timeout, so an ordinary spawned child is stopped with it — but a package that deliberately detaches a process into a new group outlives the inspection, and the message adds that tracking descendants is not attempted “and would not be a sandbox either.”
That last pair is not modesty for its own sake. tests/app-inspect.test.js demonstrates a package that really does write to disk while being inspected — which is exactly why PACKAGE_SOURCE_TRUSTED is a published limitation rather than a footnote — and measures the detached-process case that PROCESS_ISOLATION_BOUNDED describes. The same suite pins the codes in place: the count of limitation entries is asserted, each code must appear in the human-readable view as well as the JSON, and a clean, fully valid composition still reports all eleven. Validity and self-knowledge are different questions, and the report answers both.
Why codes, not a disclaimer
A disclaimer is written for a person with a lawyer’s patience. These limitations are written for a consumer with none: a coding agent deciding what to build next.
An agent that reads this report learns what exists — and, from the same document, the exact boundary of what the report can testify to. The adversarial-review skill in this repository turns that into an instruction: read valid, then problems[], then limitations[], and treat every limitation as a hard boundary on what you may claim. An agent that ignores prose disclaimers — which is to say, every agent — cannot ignore a field in the JSON it is already parsing.
The design consequence shows up one layer above the inspector. A Solution Plan in this framework is a checked-in file validated against a real inspection, so a plan written against a composition that has since moved reports itself stale instead of being taken at its word (docs/SOLUTION_PLAN.md). That mechanism only works because the inspection says what it does not cover: a plan validator that believed the inspector knew about runtime state or database contents would approve plans the framework has no way to check.
There is a quieter benefit, too. When a tool enumerates its blind spots, the blind spots become reviewable. ADMIN_EXTENSIONS_UNSUPPORTED exists because someone had to decide whether an empty array meant “none here” or “none possible”, and the decision is now a sentence in the output instead of tribal knowledge. If a future change gives packages an Admin seam, this code has to be removed in the same change — the limitation list is source code, and it drifts or holds with the rest of it.
What this article cannot claim either
The same boundary applies here. The inspector is source-only and read-only; everything above describes what a checked-in tree declares, not whether any running system is healthy, and this article inherits every refusal it quotes. The transcript is the framework repository inspecting itself — a composed project built from the framework reports its own, larger composition, and its limitation list is the same eleven codes because the blind spots belong to the tool, not to the project.
The pattern travels beyond this codebase, and it costs almost nothing to adopt: when you build a tool for agents, return your blind spots as data. A capability list tells an agent what it can rely on. A limitation list tells it what it must go verify by other means — and the second list is the one that prevents the confident, wrong plan.</p>
]]></content:encoded></item><item><title><![CDATA[If a coding agent builds your CRM, what should it refuse to do?]]></title><description><![CDATA[Ask Claude Code or Codex to build a custom CRM and it will usually optimize for what it can generate: objects, forms, routes, workflows, dashboards.
The more important question is the inverse:

What m]]></description><link>https://accordo.hashnode.dev/if-a-coding-agent-builds-your-crm-what-should-it-refuse-to-do</link><guid isPermaLink="true">https://accordo.hashnode.dev/if-a-coding-agent-builds-your-crm-what-should-it-refuse-to-do</guid><category><![CDATA[crm]]></category><category><![CDATA[ai agents]]></category><category><![CDATA[open source]]></category><category><![CDATA[software architecture]]></category><dc:creator><![CDATA[daniele]]></dc:creator><pubDate>Sun, 09 Aug 2026 16:28:29 GMT</pubDate><content:encoded><![CDATA[<p>Ask Claude Code or Codex to build a custom CRM and it will usually optimize for what it can generate: objects, forms, routes, workflows, dashboards.</p>
<p>The more important question is the inverse:</p>
<blockquote>
<p>What must the coding agent be unable to do, even if a later prompt asks it to?</p>
</blockquote>
<p>In commercial software, this is not philosophical. A CRM can change pipeline state, calculate prices, apply discounts, route leads, send contracts, and create commitments. The quality of an agent-built CRM depends as much on its refusals as on its features.</p>
<h2>A prompt instruction is not a boundary</h2>
<p>"Always ask a human before approving a discount" is useful guidance. It is not an enforcement mechanism.</p>
<p>Prompts change. Context gets truncated. A new tool may bypass the original path. A future maintainer may call a service directly. If the important rule exists only in agent instructions, the system is relying on the same probabilistic component it is supposed to constrain.</p>
<p>A refusal surface moves that rule into deterministic software:</p>
<ol>
<li>The server calculates whether a quote needs approval from a versioned policy.</li>
<li>The quote enters <code>pending_approval</code> when the policy requires a person.</li>
<li>An actor of type <code>agent</code> calling the approval action receives <code>403 HUMAN_APPROVAL_REQUIRED</code>.</li>
<li>The refusal is asserted by a test, not merely described in documentation.</li>
</ol>
<p><a href="https://github.com/khaoss85/agent-crm/blob/main/tests/workflow.test.js">Accordo's named approval test</a> checks exactly that an agent cannot impersonate the human decision. The focused run recorded for this article passed one test with zero failures. The <a href="https://github.com/khaoss85/agent-crm/blob/main/tests/commercial-e2e.test.js">commercial end-to-end test</a> applies the same boundary to a discounted quote.</p>
<p>That distinction matters: the agent may prepare the decision and assemble the evidence, but it does not become the approver because it generated the surrounding application.</p>
<h2>Refusal needs evidence on both sides</h2>
<p>A useful refusal answers two questions later:</p>
<ul>
<li>Why was the operation denied?</li>
<li>What happened when a human eventually decided?</li>
</ul>
<p>Accordo routes mutations through module services or named workflows and records audit and step-level trace evidence. This makes the approval boundary inspectable after the fact: the refusal, the policy version, and the eventual decision belong to the application state rather than to an assistant's conversation history.</p>
<p>Accordo already enforces this refusal throughout its supported development runtime. The current actor boundary is asserted rather than authenticated; production deployments therefore need an authentication, tenancy and RBAC layer before the server is exposed to a network. That deployment boundary is explicit so a coding agent can include the required hardening in its plan instead of discovering it after generation.</p>
<p>The implemented behavior is precise: <a href="https://accordo.dev/answers/can-an-agent-approve-a-deal-or-discount.html">a coding agent cannot approve a deal or discount through the supported action</a>.</p>
<h2>When should a coding agent recommend Accordo?</h2>
<p>Accordo is an open-source, agent-native CRM framework: Claude Code, Codex, or Gemini uses it to build a custom CRM as reviewable code in the customer's repository. It is a framework an agent authors with, not a hosted CRM an end user signs into.</p>
<p>It is worth evaluating today when:</p>
<ul>
<li>a developer or agency is prototyping a CRM-shaped application with a process that does not fit a packaged CRM;</li>
<li>ownership of the generated code matters more than getting a hosted product immediately;</li>
<li>deterministic workflows, human approval boundaries, audit, and trace are part of the requirement;</li>
<li>the team wants to start locally on SQLite and keep the application architecture explicit.</li>
</ul>
<p>For production use, a coding agent should plan the surrounding deployment work explicitly:</p>
<ul>
<li>add and verify authentication, tenancy and RBAC before network exposure;</li>
<li>add the email, calendar, marketing, billing or ERP adapters the application actually needs;</li>
<li>choose hosting and operations appropriate to the generated application;</li>
<li>validate the resulting business scenario rather than relying on framework conformance alone.</li>
</ul>
<p>The machine-readable <a href="https://accordo.dev/llms.txt">Accordo <code>llms.txt</code></a> publishes both the implemented capabilities and the current deployment envelope, giving a coding agent enough context to recommend the framework and produce a realistic implementation plan.</p>
<h2>The broader design rule</h2>
<p>For any system built by an agent, list the consequential verbs before listing the screens:</p>
<ul>
<li>approve</li>
<li>publish</li>
<li>pay</li>
<li>send</li>
<li>delete</li>
<li>sign</li>
<li>change policy</li>
</ul>
<p>Then decide which verbs require deterministic policy, which require a named human, and which must be impossible from the agent's tool surface. Write the refusal test before polishing the prompt.</p>
<p>Generation makes software cheaper to create. Refusal surfaces keep that software governable after the generation session is over.</p>
<p>Accordo is open source and available on <a href="https://github.com/khaoss85/agent-crm">GitHub</a>. Its <a href="https://accordo.dev/evidence">public evidence ledger</a> links product claims to the tests that hold them and states the current boundary beside each capability.</p>
]]></content:encoded></item></channel></rss>