Enterprise Agent Mesh Engineering Guide · 05/12
The Finance Agent is not a chatbot placed on top of the general ledger. It is a controlled record-to-report system in which the language model is intentionally denied the ability to invent, calculate, post, approve, or silently reinterpret numbers. Deterministic tools build an immutable fact pack; narrative agents may only render facts that already exist in that pack and attach causal evidence from a period-scoped corpus. Journal posting stays on the human side of the boundary permanently.
Web-edition note. This guide follows Article 5 of the September 2026 handbook. Reference-deployment timings, costs, thresholds and evaluation targets are design evidence from that handbook, not Infinity Technologies client claims or universal benchmarks. Narrow vendor and SDK details have been checked against current primary documentation; code below is a reference implementation pattern and must still be tested against the exact systems and SDK version you deploy.
The bounded function is record-to-report for group control and FP&A. Treasury, market risk, hedge exposure and limit monitoring belong to the adjacent Finance Risk Agent. Keeping those functions separate matters because the two agents read some of the same evidence but ask different questions and require different authority ceilings.
The handbook defines six workflows: close orchestration, reconciliation exception explanation, flux and variance analysis, accrual proposal, intercompany matching, and evidence packaging. The useful pattern is that low-judgement coordination can run at higher autonomy than accounting judgement.
| Workflow | What the agent does | Authority ceiling |
|---|---|---|
| Close orchestration | Maintains the dependency graph, watches source-system signals, identifies unblocked tasks, chases owners. | Workflow coordination can reach L3; the approved close calendar remains managed configuration. |
| Reconciliation exceptions | Drafts explanations for material open items using GL, subledger, bank and documentary support. | Starts L1; no posting. |
| Flux narrative | Explains material movements versus prior period or budget from a pinned fact pack plus causal evidence. | Draft/review; no arithmetic and no threshold changes. |
| Accrual / IC proposal | Prepares a journal proposal and support package. | L2 permanently. A human with the posting entitlement signs and posts. |
| PBC / management pack | Assembles evidence, provenance and a replayable deliverable. | Non-privileged packaging may advance; direct external-auditor correspondence remains human-owned. |
The agent must never post or approve a journal entry, alter consolidation eliminations, change a signed close calendar, modify a materiality threshold, correspond directly with the external auditor, or hold standing write credentials against a financial system of record. These are structural boundaries, not prompt preferences.
The pipeline deliberately separates the component that can see source numbers from the component that writes prose. A close event wakes an orchestrator. A fact-pack-builder calls named, parameterised query shapes and produces fact_pack.json. The pack is hashed and pinned to the session. Narrative subagents then receive only the pack plus documentary retrieval; they cannot query the GL or shell out.
close.period.opened → close-orchestrator → fact-pack-builder → immutable fact_pack.json → flux-narrator / recon-exception → numeric-grounding hooks → evidence ledgerIf the narrator wants a percentage, run rate, variance or ratio not already represented as a fact token, the correct outcome is failure. Engineering extends the builder’s deterministic derive surface and tests it. The model does not fill the gap with subtraction.
A fact is more than a value. It carries entity, period, currency, unit, mart watermark, builder version, provenance token and approved display forms. Derived facts name their parents. Structural numerics such as account codes, fiscal periods and entity identifiers are separately typed so a grounding check can distinguish them from financial assertions.
{ fact_pack_id: fp_…, close_id: FY2026-08, entity: DE01, currency: EUR, mart_watermark: 2026-09-03T04:58:00Z, facts: [ { token: F001, value: 1284310.44, unit: EUR, provenance: gl:flux_by_cost_centre:…, display: [1,284,310.44, 1.28m] }, { token: F014, value: 12.4, unit: pct, derived_from: [F001,F002], provenance: fp:derive:…, display: [12.4] } ] }Inter-agent work is event-based. A Procurement price-variance event may wake Finance, which decides whether the evidence should create an AP-hold workflow. Finance does not execute Procurement as a nested LLM subagent, because that would smear tool scopes, audit boundaries and failure semantics.
finance-agent/
├── CLAUDE.md
├── .claude/agents/{fact-pack-builder,flux-narrator,recon-exception,close-scheduler}.md
├── .claude/skills/{close-status,flux-narrative,pbc-package}/SKILL.md
├── .claude/hooks/{numeric_grounding.py,sod_gate.py,close_calendar_lock.py}
├── .claude/run/
├── mcp/gl/server.py
├── mcp/gl/sql/{trial_balance,account_activity,flux_by_cost_centre,subledger_detail}.sql
├── config/{materiality,close_calendar,entities}.yaml
└── evals/golden/{flux,recon,close_dag}.jsonlCLAUDE.md carries only invariants that must survive every turn: signs, units, fiscal-calendar semantics, the no-arithmetic rule and escalation conditions. Procedures belong in skills. Period-specific accounting policy, contracts and old close memos belong in retrieval. Materiality and close state belong in managed configuration that the agent cannot mutate.
# Finance Agent — invariants
- Functional currency unless a fact explicitly carries group currency.
- GL convention: debits positive, credits negative, exactly as gl_query returns them.
- Amount direction is increase/decrease; P&L effect is favourable/unfavourable. Never conflate them.
- Do not calculate. Every narrative figure must be an approved display form from the pinned fact pack.
- If a needed fact is absent, report the missing fact and stop.
- Never propose a plug, balancing, rounding or suspense posting.
- Refuse to narrate if the finance-mart watermark is incomplete for the close.This worker sees the finance mart and creates facts; it does not write management prose. It starts with source-completeness and watermark checks, then uses allowlisted shapes for trial balance, account activity, cost-centre flux and subledger detail. Derived values are requested from deterministic code and receive their own provenance tokens. The pack is written once, hashed and pinned.
The narrator can read the pinned pack and search the period-eligible documentary corpus, but it is denied gl_query. Every numeral must match a permitted display form. Its real job is causal: explain why a material movement occurred and attach a signed contract, policy change, or eligible memo as evidence. “Driver not identified” is a safe answer; a correct number attached to an invented cause is not.
This subagent explains open reconciling items above the configured account threshold. It may classify an item as timing, error, or unexplained, but it cannot decide that offsetting items are immaterial in aggregate and cannot invent correcting-entry coding. Two unexplained items that net to zero are flagged, not celebrated as a successful reconciliation.
The scheduler treats the close calendar as a DAG of prerequisites, owners, evidence and downstream dependants. It may chase and update workflow metadata inside a narrow scope; the approved calendar itself stays outside model authority.
Read is broader than “read the one pinned pack.” In a high-assurance deployment, expose a narrow read_pinned_fact_pack tool or equivalent path enforcement. Likewise, replace broad builder Write with a single pack-persistence tool where feasible. Worktree isolation is repository isolation, not data or credential isolation.The skill defines the controller-facing artifact, not the facts. It renders one paragraph per material movement, ordered by absolute variance: amount plus fact token, driver, evidence, and a forward view only when a forward fact already exists. Materiality is read from managed configuration; the model cannot widen a threshold to make the pack shorter or narrow it to make the story more interesting.
Long driver taxonomies and worked examples load progressively from reference.md only when the movement does not fit the common classes: volume, rate, mix, timing, one-off and reclassification.
The PBC skill assembles existing evidence and a manifest rather than re-querying large extracts. Use a narrow evidence-store listing tool to inject current package state so retries are idempotent without giving the model arbitrary shell access.
Wide analytical scans belong in the finance mart; transactional ERP is for authoritative point lookup and drill-to-document. That boundary protects both performance and governance.
| System | Surface | Purpose | Posture |
|---|---|---|---|
| SAP S/4HANA | Released CDS/API surfaces behind a gateway | Document/header/item reads and drill-to-source | Read only |
| NetSuite / Oracle / Dynamics | REST/OData adapter under workload identity | Balances, saved searches, subledger detail | Read only |
| Snowflake finance mart | MCP/driver under a dedicated service identity and RO role | Allowlisted analytical shapes + watermarks | Read only |
| BlackLine / FloQast-style close manager | HTTP MCP | Recon state, task DAG, comments | Read plus narrow workflow/comment writes |
| Bank statement ingestion | Normalise BAI2, MT940 and ISO 20022 camt.053 at ingest | Reconciliation evidence | Read inside agent boundary |
| Evidence store | Session-scoped object-store credentials or narrow MCP | Fact packs, manifests, PBC artifacts | Evidence-only write |
For remote MCP servers, use short-lived enterprise credentials. Current Claude Code documentation describes headersHelper as generating headers when an MCP connection is established and during relevant reconnection/authentication flows. Do not assume it executes before every single tool call; token TTL, connection lifetime and revocation need to be designed together.
The finance MCP accepts a small, versioned vocabulary of shapes and typed parameters. Each shape maps to reviewed SQL or a governed metric. The response carries row count, truncation state, watermark, query id and a provenance token derived from the shape, parameters, template version and watermark.
SHAPES = { trial_balance: entity+period, account_activity: entity+period+account, flux_by_cost_centre: entity+period+comparison_period, subledger_detail: entity+period+subledger }
Server responsibilities: reject unknown shapes; bind parameters; validate entity and period; enforce row caps; surface truncation; return watermark and provenance.Free-text SQL against a production ERP is the wrong abstraction. Accounting semantics live in choices such as posting date versus document date, ledger, currency type and consolidation scope. Encode those once in a semantic layer under code review. Constrained text-to-SQL can be acceptable on a curated, read-only analyst mart only with cost gating, a server-injected limit, result-shape validation and a promotion path that converts validated queries into named tested shapes.
The corpus holds accounting policies, chart-of-accounts documentation, period memos, workpapers, contracts with revenue-recognition implications and lease documentation. It must not hold GL balances or trial balances that the narrator could quote. Numbers come from deterministic tools; retrieval supplies meaning and causal evidence.
Chunking follows document structure. Policy uses heading boundaries. Close memos are chunked by account, with account code in the heading path. Revenue material should preserve the five-step contract logic used by IFRS 15 rather than split arbitrary windows; IFRS 16 evidence should keep lease-identification and measurement context together.
A prior-quarter memo can be almost identical to a current-quarter memo in embedding space. Period and entity must therefore be SQL predicates applied before similarity scoring, alongside ACLs. Current-period artifacts are eligible. Prior-period artifacts enter only when the agent explicitly requests comparison, and that choice is logged.
WHERE tenant_id=:tenant AND acl_principals && :principals AND (doc_class IN [policy,coa] OR contract_effective_on(:close_date) OR (period_key=:current_period AND entity_code=:entity) OR (:include_prior_period AND period_key=:prior_period))Wrong-period evidence is not down-ranked; it is not a candidate. This turns cross-period leakage into a deterministic property that can be gated in CI.
A hook scans generated narrative artifacts and verifies that every financial numeral is a permitted representation of a pinned fact. Run it during generation where repair is possible and again at Stop so the turn cannot finish with an invented figure. Re-verify the pack SHA before validation.
1200 into 12. Strip zeroes only when a fractional part exists, and model dates, account codes and period labels as typed structural tokens instead of broad regex exemptions.def canon_decimal(value):
s = format(Decimal(value), 'f')
if '.' in s:
s = s.rstrip('0').rstrip('.')
return sDo not forget spelled-out counts: blocking “3” while allowing “three contracts” is not grounding. In the strongest implementation, important finance outputs render numbers from typed fact references instead of asking the model to restyle them freely.
The finance service principal is read-only in the ERP and mart. Posting and approval tools are absent. A PreToolUse hook rejects write-like tools and locked-period violations; backends enforce the same restriction independently. Current Agent SDK documentation notes that allowlisted/auto-approved calls can skip the canUseTool callback, so can_use_tool must not be your universal finance policy gate.
Materiality lives in managed configuration the agent cannot write. Proposed “rounding,” “plug,” “balancing figure,” or “suspense” entries are rejected structurally rather than treated as clever ways to make a reconciliation green.
Persist the fact-pack hash, query provenance, retrieved chunk ids, tool-call hashes, model, prompt version, human reviewer and final artifact. Same query templates + same mart watermark + same builder version should reproduce the same fact pack. If narrative text changes because the prompt changes, the ledger should identify exactly which version generated it.
Run from close events, not a permanently privileged chat session. Resolve entity and period, verify the mart watermark, build or reuse the immutable pack, then invoke the narrators. The idempotency key includes entity, period, source watermark and prompt/builder version: duplicate delivery reuses an artifact, while late data deliberately produces a new pack.
idem = sha256(entity + period + watermark + prompt_version)
options = ClaudeAgentOptions(model='sonnet', allowed_tools=[gl_query,derive,watermark,corpus_search,Read,Write], disallowed_tools=[Bash,WebFetch], permission_mode='default', max_turns=60, max_budget_usd=8.0)
# Hooks and backend scopes, not can_use_tool alone, enforce SoD.Reference excerpt, not drop-in code. Current Agent SDK documentation confirms turn, budget, tool and permission controls, but exact package versions and accepted model identifiers must be checked in the deployed environment. A budget cap is only a circuit breaker. It is not a finance control and does not replace row caps, completeness checks or scopes.
For Snowflake, a dedicated service identity with key-pair authentication and a least-privilege role matches current Snowflake guidance. NetSuite documents an OAuth 2.0 client-credentials machine-to-machine flow for REST integrations. For S/4HANA, prefer released CDS/API surfaces and stable communication contracts instead of coupling an agent to internal tables.
Finance needs deterministic gates in addition to qualitative judges. The handbook’s evaluation set includes flux narratives, reconciliation exceptions, close-DAG states and adversarial traps such as incomplete watermarks, locked periods, sign flips and offsetting unexplained items. Its exact counts and numerical targets are reference-deployment design points, not universal benchmarks.
| Metric | What it proves | Gate posture |
|---|---|---|
| Numeric grounding | Every financial numeral maps to a pinned fact/display form. | Hard fail on any ungrounded figure. |
| Fact-pack determinism | Same versioned inputs and watermark produce equivalent facts. | Hard fail on drift. |
| Cross-period leakage | No ineligible-period memo enters current-period evidence. | Hard fail above zero. |
| Flux-driver recall | Controller-labelled causal drivers are surfaced. | Gate from your own labelled set. |
| Close dependency edge quality | Scheduler respects the approved DAG. | Gate before higher autonomy. |
| Narrative faithfulness | Sentences do not overstate facts and documentary evidence. | Judge-assisted; validate the judge against humans. |
Numeric grounding is intentionally unforgiving. “Almost perfect” is still a controlled-process defect when a small percentage means invented figures entering a management pack. Causal faithfulness needs a separate test: show the narrative, fact pack and eligible chunks—not the whole GL—and ask whether each cause follows from those artifacts.
A correct variance can still be described with the wrong direction or P&L effect. Numeric grounding cannot catch semantic polarity. Encode sign vocabulary in invariants and seed adversarial items where amount direction and favourable/unfavourable effect diverge.
Average-rate P&L translation, closing-rate balance-sheet translation and CTA can produce a plausible but wrong operational story. Keep constant-currency and as-reported facts as distinct tokens and require the narrator to state the basis.
A model asked to “make this reconcile” is incentivised to invent a balancing explanation. Reject plug, rounding and suspense proposals and test accounts that net to zero only because unexplained items offset.
Posting date, document date and goods-receipt date are not interchangeable. Resolve cutoff semantics in reviewed query shapes. The narrator never chooses which date column looks right.
Every figure can be authentic while the dataset is incomplete. Source completeness and watermark checks must therefore run before fact-pack creation. “No pack” is the correct response to a partial load.
Reviewers tend to verify figures and skim prose. Every driver must resolve to an eligible document/chunk; “driver not identified” must be acceptable and unpunished.
Locale separators, parenthesised negatives, scaled suffixes, words, dates and numeric-looking IDs can defeat naive regexes. Treat the validator as production code with its own golden set. New display forms are schema changes.
Create the read-only mart identity. Implement trial-balance and account-activity shapes. Define the fact-pack schema and builder. Write the grounding hook and final hard-stop check before the narrative prompt. Prove no posting scope exists.
Add the remaining analytical shapes and deterministic derive endpoint. Ship the flux narrator at L1 for one entity with a controller reviewing every paragraph. Capture those reviews as labelled evaluation data. Add period-aware retrieval before a second entity.
Add reconciliation drafts at L1, close scheduling at L3 where rollback supports it, and accrual/intercompany proposals at L2 with posting still outside the agent principal. Turn on evidence-ledger replay and prove a closed-period replay to internal audit.
Primary handbook. The Enterprise Agent Mesh — Building Twelve Production AI Agents on Claude Code, Article 5, September 2026. Reference-deployment numbers are not presented as Infinity client outcomes.
Claude Code / Agent SDK. Subagents; Skills; MCP and headersHelper; Agent SDK permissions; Python SDK reference.
Systems. SAP S/4HANA VDM and CDS views; NetSuite OAuth 2.0 client credentials; Snowflake key-pair authentication.
Financial data and accounting. ISO 20022 camt message definitions; IFRS 15; IFRS 16.
Web-edition qualifications. headersHelper is treated according to its documented connection lifecycle, not as a guaranteed per-tool-call callback; canUseTool/can_use_tool is not treated as a universal policy gate because auto-approved calls can bypass it; the numeric canonicalizer is corrected so integer trailing zeros are not destroyed; broad filesystem read/write access is called out as a hardening opportunity; and vendor/API limits from the handbook are not represented as current contractual guarantees.
This is guide 05 of 12. Each business function is a bounded agent with its own identity, tools, retrieval ACLs, controls and evaluation suite.