Dhruv Patel

← Work

Silverpond

An architecture in which each new customer onboards with three inputs and Silverpond stores no AWS keys at all. I proved it in a FastAPI prototype, reviewed it with the senior engineers, then implemented it in the Rails product.

Software Engineer (AI) intern · May–Aug 2026 · Python, FastAPI, Ruby on Rails, AWS (STS, ECS Fargate, CloudFormation), Anthropic Managed Agents

Follow the work

ANTHROPIC · CLAUDE PLATFORM ON AWSCUSTOMER’S AWS ACCOUNTOperatorHighlighterthe gateway · RailsManaged agentthe brain · ClaudeWorkerthe hands · ECS FargateHighlighter dataGraphQL APIsession · prompttool calls · polledhl CLI → GraphQLANTHROPIC · CLAUDE PLATFORM ON AWSCUSTOMER’S AWS ACCOUNTOperatorHighlighterthe gateway · RailsManaged agentthe brain · ClaudeWorkerthe hands · ECS FargateHighlighter dataGraphQL APIsession · prompttool calls · polledhl CLI → GraphQL

1 / 6

An operator asks about a monitoring case

The question arrives in the Highlighter app, attached to its case.

Where the worker runs

Execution and data stay inside the customer’s own account. The review made this the primary path for enterprise customers.

Tap any box to see what that layer owns. Built both ways during the internship; the code is Silverpond’s and isn’t public.

diagram · the architecture from my senior review, customer names removed

How it was earned

The ambiguity

The brief was one paragraph: operators should be able to chat with an agent about a monitoring case, the agent should query the relevant data, the knowledge should be searchable, and users should be able to add lessons. What it didn't say was how to split that work across three systems (the platform's Rails app, Anthropic's managed agents, and a worker container), or how to do it safely for every customer who comes after the first. That became the question I brought to the senior review: how do we split responsibility cleanly, securely, and in a way that scales to every new customer?

Two products were being treated as one

The direction was Claude's managed agents on AWS, but the feature requests kept describing what Amazon Bedrock provides. I compared the two side by side, showed where the requirements were mixing them, and we settled on managed agents. Then I built and tried both ways of running them: a self-hosted worker in the customer's AWS account, and Anthropic's hosted sandbox. They trade off differently: the hosted sandbox needs no standing worker per customer, so it's cheaper to run, while self-hosting keeps execution and data inside the customer's own account. The review deck presents both, with self-hosted as the primary path for enterprise customers.

Prototype before production

I built the workflow in FastAPI first, a stack I could move fast in, so the design could be proven before anyone committed to changing the Rails product.

The agent was slow because it was free to wander

  1. SAWLeft to search the knowledge base however it liked, the agent wandered.23.4 sfirst-turn search
  2. CHANGEDIndex-first retrieval: turn one reads only the index, turn two reads at most two files in parallel.3.9 sfirst-turn search
  3. CHANGEDThe reference corpus moved into a memory store, out of every request.−3.5ktokens per request
  4. CHANGEDCold start, with the same two changes.59.2 → 42.6 scold start
  5. HOLDSThe second turn, which reads at most two files.8.7 srepeated runs
  6. NOT YETA cold start still takes about 43 seconds.
measured · repeated runs · named stress and latency tests

Scope was enforced in code, not asked for in the prompt

Queries that should never run, such as reaching into the staging database, are classified into tiers before the model acts, and refused in 3.3 s with zero tool calls.

measured · repeated runs

Internal reasoning was leaking into answers

I extracted the answer by a marker and kept intermediate tool turns silent, which also brought a cache-hit response to 7.6 s.

A platform limit I didn't decide on alone

The managed-agent API only returned text when a turn finished, so nothing streamed. I shipped a typewriter-style display as a stopgap, and put the real question to the team: is block-by-block latency acceptable, or do we simulate streaming?

Customer credentials

The simple path was to ask each customer for AWS access keys. Instead, Silverpond assumes a role in the customer's account through STS, with the ExternalId bound to that customer's account ID (the defence against a confused-deputy attack). Credentials last one hour, and the customer can revoke access at any time. Onboarding is a one-click CloudFormation stack plus three inputs. Tenants are isolated at six layers: database scope, container cluster, agent environment, memory store, vault and network.

The integration fought back, and I wrote it down

Signing requests to the managed-agent gateway, and knowing which storage primitive accepts what, took empirical work. I put every one of those findings into the handover, so the next engineer doesn't rediscover them.

What stands

  • An architecture review the senior team could decide from.
  • A six-step provisioning state machine.
  • My Rails integration (schema, STS role assumption, the managed-agent API client, the provisioning job and the onboarding UI), passing 8/8 RSpec with 0 RuboCop offences.
  • Onboarding reduced to three inputs, with zero stored AWS credentials.

What it still didn't do at handover

  • Two integration threads were still open: attaching files to the memory store, and the worker's request signing.
  • The worker processes one case at a time. Its concurrency policy was a question for the team.
  • A cold start still took ~43 s.

Sources

  • The architecture review I presented to the senior team, and the integration guide in the handover. Internal to Silverpond.
  • The prototype's named stress and latency tests, and the handover notes. Internal to Silverpond; the code isn't public.