437plaintext tool-result records encrypted in place across 64 conversations, 0 failures, verified three ways

Giving an AI assistant real access to a company's data

Agentic tool access · Security and access control · 13 min read

Corporate OAuth and four agentic tool servers added to an internal AI assistant, plus the security engineering that made giving a language model write access to mail, chat and calendars defensible.

→ Four tool servers live behind one consented identity. The assistant acts on a user’s own mail, chat, calendar and documents, and never sees a credential.

  • Go
  • Python
  • Vue 3
  • MongoDB
  • Valkey
Read →
$1,299/mothe subscription tender-response product the in-house system displaced, gross, as billed

Answering tender questionnaires from a knowledge base that contradicted itself

Retrieval and RAG · Measurement and cost · 15 min read

A three-tier answering path (exact match, semantic match, retrieval-augmented generation) built over a corpus of roughly 3,900 reusable question-and-answer pairs, and what measuring that corpus revealed about trusting it.

→ The in-house tender answering system that displaced a $1,299/month commercial subscription, answering from the company’s own corpus after auditing it.

  • Go
  • MongoDB
  • AWS Bedrock
  • OpenSearch
  • Embeddings
Read →
93%largest measured cut in the input tokens one request carried: 30k down to 2.2k

The thirty-thousand-token tax on asking what time it is

Agentic tool access · Measurement and cost · 16 min read

A per-user tool toggle and an embedding-based relevance gate in front of the model call, cutting the fixed token cost of having tools at all, plus the measurement that deleted the cleverest part of my own design.

→ The fixed cost of having tools at all, cut by up to ≈93% on a message, and the cleverest part of my own design deleted on its own evidence.

  • Go
  • Vue 3
  • TypeScript
  • MongoDB
  • AWS Bedrock
Read →
0 writesoperations either proxy exposes. Least privilege is enforced in the proxy, because neither vendor's token could express it

Two vendor integrations, and the least privilege neither token could express

Agentic tool access · Security and access control · 14 min read

A read-only proxy to a compliance-automation platform and a delegated integration to a device-management platform. One authenticates as the organisation, one as each user, and the access control had to move somewhere else in both cases.

→ Two vendor integrations live and read-only by construction, with least privilege enforced in the proxy because neither vendor’s token could express it.

  • Python
  • Go
  • MCP
  • OAuth 2.0
  • Docker
Read →
$0committed to a paid feed, against four candidates at $5k–$12k a year each. Every source optional, the pipeline correct with none

Measuring an agentic SOC triage pipeline before improving it

Agentic tool access · Measurement and cost · 20 min read

A multi-source indicator enrichment pipeline behind a cross-tenant cache, a grounding-and-validation layer that stopped a model attributing attack techniques from memory, and a labelled ground-truth baseline built before any of it was tuned.

→ An enrichment pipeline running on free-tier sources with no spend committed, plus the labelled baseline that makes any future tuning measurable.

  • Go
  • MongoDB
  • Valkey
  • AWS Bedrock
  • MITRE ATT&CK
Read →
1 of 3answer columns the layout detector found in a real workbook, while reporting its confidence as high

Filling in a spreadsheet you are not allowed to redesign

Document pipelines · Retrieval and RAG · 16 min read

Answering a buyer's supplier response schedule inside the buyer's own workbook: resolving which columns are answers, deciding which rows are questions at all, generating one value per cell against the column's own vocabulary, and reporting honestly on everything withheld.

→ Several-hundred-row tender workbooks come back filled in and structurally intact, with 169 machine-written rows checked line by line against human ones.

  • Go
  • MongoDB
  • AWS Bedrock
  • Retrieval-augmented generation
  • Excelize
Read →
0 of 3,307indexed chunks carrying the tag a new filter was about to key on, checked before it was built

The gate that would have been a deletion

Retrieval and RAG · Security and access control · 14 min read

Admitting a class of third-party vendor documentation into a retrieval library without letting it answer questions it has no business answering, and finding, before shipping, that the filter as designed could only ever subtract.

→ Per-bid control over which content may answer a question, shipped with the interface that sets it, after catching that the filter as designed could only subtract.

  • Go
  • MongoDB
  • OpenSearch
  • AWS Bedrock
  • Object storage
Read →
0model calls in the review report's first phase, which is arithmetic and ships useful on its own

The half of the report I refused to generate

Retrieval and RAG · Document pipelines · 19 min read

Two AI-generated reports on a bid, and a third that judges the bid's own answers. It includes a grader that had to declare which of the answers it was marking had already seen the mark scheme, and a set of sections deliberately left as empty boxes for a human to type into.

→ Kickoff decks and review reports generated from what the system actually knows, with about two fifths of the deck left as empty boxes rather than invented.

  • Go
  • MongoDB
  • OpenSearch
  • AWS Bedrock
  • AWS KMS
Read →
1 of 108reference answers reachable under any single question wording, so “give me three” could not be answered

The only answer whose value is the customer's name

Retrieval and RAG · Document pipelines · 16 min read

Every tender asks for three customer references matched to the work. The corpus already held a hundred of them, unreachable by construction, and the one part of the tab the system did answer filled a referee's phone number with the supplier's own.

→ Customer references now selected per bid by product and sector, where no single question could previously reach more than one of the 108 in the corpus.

  • Go
  • MongoDB
  • AWS Bedrock
  • AWS KMS
  • BM25
Read →
2 msp50 once an endpoint stopped waiting on a decrypt no handler read, while its siblings ran 174–304 ms

The optimisation that would have bought one per cent

Measurement and cost · 20 min read

One page load spent roughly twenty-eight key-management round trips decrypting a field no handler anywhere reads. One returnable workbook took seventy to eighty minutes. The first was measured and fixed; the second was measured, and the change everyone reaches for first was dropped.

→ A bid page that stopped waiting on a decrypt nobody reads, and an obvious optimisation measured at ≈1% of wall clock and dropped rather than shipped.

  • Go
  • MongoDB
  • AWS Bedrock
  • AWS KMS
  • OpenSearch
Read →
0external integrations in the final design, after the CRM turned out to be a different product entirely

There is no buyer

Document pipelines · Retrieval and RAG · 18 min read

"Learn more about this buyer" was a card that had shipped disabled months earlier. The system stored the buyer as free text with a substring search over it, recorded no won-or-lost outcome, and let its audit feed expire at a year. The feature was an identity problem wearing a reporting problem's clothes.

→ Win/loss history that follows a buyer across tenders and questionnaires, with zero external integrations. The fix was a data model, not a CRM link.

  • Go
  • MongoDB
  • Vue 3
  • AWS Bedrock
  • OpenSearch
Read →
44routes that required only a valid session, including a bulk delete of the shared answer corpus

The role restriction that guarded nothing

Security and access control · Measurement and cost · 16 min read

The feature had a role, a flag and an admin tab, and forty-four of its routes asked only whether the caller was signed in. Fixing it meant separating four gates that get discussed as one: does this exist, who is it for, how much of it may they use, and who decides that from outside the code.

→ Forty-four unguarded routes closed, the most expensive calls in the product metered for the first time, and the frontend gate now fails closed.

  • Go
  • Gin
  • Vue 3
  • MongoDB
  • Valkey
Read →
0 of 658logged answering attempts served by a cache that was wired up, logging, and had never once hit

The cache that had never served an answer

Retrieval and RAG · Measurement and cost · 15 min read

A three-tier answer cache that was wired up, logging, healthy and passing its tests had served zero answers in its entire life. The reason was a gate reading one number as if it were a different one.

→ The cheap answer path switched on for the first time, after finding two stacked defects that kept it dark across 658 attempts.

  • Go
  • MongoDB
  • AWS Bedrock
  • Retrieval-augmented generation
  • Cost measurement
Read →

Everything here is generalised: the engineering is described, my employer's systems are not. More are written up as they're cleared for publication.