Lehi, Utah — July 9, 2026
Today at a well-attended builder-focused AWS Utah gathering in Lehi, the local e-commerce technology company Pattern pulled back the curtain on Pi — short for Pattern Intelligence — the AI agent it has spent the past several months building and rebuilding into a system now handling messages for thousands of users.
The event, co-hosted by AWS Utah, Codebase, and Pattern, drew a room of engineers, founders, and AI-curious operators for high-end Indian cuisine, generously sponsored by TrueMark of Pleasant Grove, Utah, and a technical walkthrough that was less product pitch than deep-dive engineering post-mortem: what the Pattern team tried, what broke, and what they'd tell other teams building agents today.

Codebase CEO Jon Bradshaw welcomed the room, generated a rich discussion among the dozens of attendees, before handing things over to three seasoned Pattern engineers.
Chief Architect Jason Wells has been with Pattern since the company's earliest days, back when it started as iServe, out of a modest warehouse, off the beaten path, in Lehi, in 2013. He opened with a quick tour of that history: a string of acquisitions and homegrown products over the years, and, more recently, a growing patent portfolio, including U.S. Patent No. 11,321,724, issued in 2022 and covering the company's Destiny ad-tech product, and U.S. Patent No. 12,626,273, issued in 2026 and covering its True ROAS product.

Betting on primitives, not frameworks
With that patchwork of acquired products and years of accumulated data behind it, Pattern's goal for Pi was to build a single "always-on" intelligence layer that could reason across all of it, rather than treating each product as its own island.
Before getting into the architecture, Wells outlined the governing principles the team set for Pi from the outset: a chat experience that's personalization-aware, a push/pull interaction model (so Pi can proactively act, not just respond), deep business-expertise modeling, and "white glove" handling of complex, multi-step tasks.

He described Pi's AI-agent layer as something like an app store, i.e a platform other capabilities plug into, built on top of Pattern's data advantage, which Wells put at roughly 77 terabytes of proprietary data points. The system is also designed to incorporate technology from outside Pattern, not just its own tools.
All of it, Wells said, sits on top of one non-negotiable foundation: trust and accuracy.
The team's central decision was to avoid locking into any one agent framework. Instead, they built their own internal abstraction. Wells called it an "agent server factory" that defines a common interface. Any number of frameworks can plug in underneath it. Pattern launched with three supported simultaneously: CrewAI, Vercel's AI SDK, and Mastra.
That decision paid off directly. Pi originally ran on Mastra, but the team later found the framework too opinionated for how they wanted the agent to behave. Because the underlying architecture didn't depend on any single framework, switching to the AI SDK took one pull request: about 280 lines, the vast majority of it routine import changes rather than new logic.
The same philosophy shows up throughout the system: a "channels" layer lets Pi be reached from email, Slack, Microsoft Teams, SMS, or chat clients like ChatGPT and Claude, with each channel simply plugging into the same core agent. A "stored tool" layer unifies hand-written tools, MCP servers, and sub-agents into one searchable pool, so the agent can pull in only the tools relevant to a given request rather than being handed all of them at once.

The unglamorous problem that mattered most: memory
Some of the most consequential engineering discussed wasn't the flashiest. Pattern built "memory adapters," i.e. simple save-and-retrieve interfaces, as a way to plug in different memory backends without committing to one. That flexibility led the team to a bigger discovery around prompt caching, the practice of reusing previously processed conversation context to reduce AI model costs.

Pattern had been dynamically altering its system prompt as new information came in, which broke the model provider's cache every time. By instead using memory adapters to gather all dynamic context in parallel and append it as a single message at the end of the conversation history, the team preserved caching further up the chain. Pattern says it now sees a roughly 90% cache hit rate on those tokens, a meaningful cost difference at scale.
A related fix addressed a wave of formatting errors the team was seeing from Anthropic's Claude models, tied to strict rules about how conversation turns and tool calls must be structured. Rather than reconstructing the full message history at the end of each turn, Pattern moved to saving each step as it happened, an event-driven approach that eliminated the errors and, as a side benefit, made it possible to inject messages mid-turn or surface interactive UI elements inline in chat.

jq and cat, rather than loading it directly into the model's context window. Photo: Mark Tullis, TechBuzzGiving the agent a file system
Engineer Ryan Shaw walked through Pattern's virtual file system (VFS), a stateful workspace the team built on top of AWS Bedrock AgentCore's ephemeral compute sandbox, giving Pi a persistent place to read and write files even though the underlying sandbox itself is thrown away after each run.
The scenario Shaw used to frame the problem: a user looking at any chart or graph on any page asks Pi, "Tell me about what I am looking at on this page." Handing the model the page's raw HTML wouldn't work, Shaw said, and passing in the full underlying JSON data would blow up the context window.
Instead, Pattern exposes that data as an annotated .json file in the VFS, and lets the model use ordinary file-reading tools to pull out just what it needs.

Shaw described the system as bidirectional: before a sandbox runs, relevant files are packaged and mounted into it from the VFS; after it finishes, any new or modified files and output logs get extracted and synced back. He noted AWS has since added similar file-system configuration options natively to AgentCore Runtime, but Pattern built its version independently.
Gavin Ritchie added that permissions follow the same rules already governing what a user can see and do in Pattern's product, and that certain actions can be flagged to require explicit user approval before the agent executes them.
Wells also sketched the broader system Pi sits inside, beyond the specific AWS request flow, a wider architecture where requests from channels like Slack, ChatGPT, or Pi's own interface reach a shared agent layer that coordinates with a task registry and tracker, a knowledge management system, an internal tool-building system Wells referred to as "Toolsmith," and a sensor-driven automation layer feeding off Pattern's broader data lake.

Scaling without much drama
Asked how the system has held up under growth, Wells said Pattern has gone from a few hundred users to several thousand, and from a modest volume of messages to millions, without significant rework. He credited that mostly to getting the underlying primitives right early, along with continued improvements to AWS Bedrock AgentCore itself, including added support for durable, resumable agent runs.
The team also described a rigorous evaluation process for shipping changes: new tools and prompt changes are tested against internal question sets before being promoted from an "aspirational" bucket into the core suite that must reliably pass. Feature flags allow the team to test changes with a subset of users before a wider rollout.
Learn more about Pattern's Pi here. A deeper technical discussion is shown below. Learn more about AWS Utah events here.

Editor's note: Jon Bradshaw led a discussion involving many attendees that had community updates and open roles in their organizations, including at AI transformation consultancy RIT Intelligence and from Vivint's data and AI team.
TrueMark (Pleasant Grove, Utah), an AWS Advanced Tier partner and the event's over-performing lunch sponsor, also pointed attendees to AWS's proof-of-concept funding program, which can put up to $25,000 in cash — not just cloud credits — behind a scoped build.
Nick Baguley, Founder of Bad Labels AI, shared "Prompt Pivot Pitch," an AI build challenge series that brings entrepreneurs, developers, and problem owners together to refine real-world AI solutions, form teams, and prepare investor- and community-ready pitches through collaborative workshops and networking events.
And finally, Pattern announced it is hosting a hackathon with Google DeepMind the following weekend centered on Google's Gemma model family, with $2,000 in prizes.
Sidebar: Under the Hood — Pattern's Agent Architecture, for Builders
The following is a closer technical look at the systems Pattern's engineers described, for readers maybe building agents of their own and wanting to chew on more detail:
Framework abstraction. Pattern's "agent server factory" defines one base interface handling shared concerns — health checks, file-type support, security — and lets framework-specific implementations (CrewAI, Vercel AI SDK, Mastra) plug in underneath. A developer defines an agent's instructions and model once and can serve it through any supported framework without rewriting the agent itself. As shown on one of Jason Wells's slides, the pattern for wrapping a plain agent definition for a specific framework is straightforward:
javascript
const aiAgent = new Agent({
instructions: CHATBOT_SYSTEM_PROMPT,
model: agentModel('gpt-5-mini'),
})
export const chatbotAgent = createAISDKAgent(
aiAgent,
basicMemoryAdapter,
)Channels and the handler boundary. Pattern's term for the channels pattern is a "handler boundary": every incoming request, regardless of source. Pi's own interface, email, Slack, Microsoft Teams, ChatGPT, or Claude pass through channel-specific resolution and comes out the other side as the same normalized agent request. The result, per Ritchie's slide, is "zero logic duplication": core agent capabilities are written exactly once, and only the thin resolution layer differs per channel.
Tool retrieval. As Pattern's tool count grew across hand-written code tools, MCP servers, and sub-agents, the team moved from basic embedding search to embedding search with re-ranking, and eventually added a BM25-style keyword-matching algorithm, swappable independently of how tools are defined.
Memory adapters. Pattern's own internal name for this pattern is "memory primitives." Ritchie called it "a secret superpower." The core interface is a simple save_messages / retrieve_messages contract, so any memory backend (a database query, a knowledge base lookup, a cache) can plug in the same way. As shown on one of Gavin Ritchie's slides, a minimal adapter looks like this:

javascript
export const testMemoryAdapter = createSecondaryMemoryAdapter({
source: 'test_memory',
async fetchContent({ userId, input, options }) {
...
}
saveFn: async () => {
...
}
})Not every adapter needs a saveFn.Many are read-only lookups. Pattern runs a large roster of these "secondary" adapters in parallel and merges their output into a single unified message. Among the examples shown in the presentations were adapters for page context, file context, user profiles, recommendations, geo-based recommendations, workspace task drafts, and MCP resources. That uniform shape and parallel-merge pattern is the basis of the prompt-caching fix described below.
Prompt caching mechanics. The team's fix relied on a specific constraint: providers like Anthropic cache a conversation prefix up to a point, and anything appended after that point is billed as new. By using parallel memory-adapter lookups to assemble all dynamic context into a single message appended at the very end of the stack, rather than editing the system prompt. Pattern preserved the cacheable prefix and reports a roughly 90% cache hit rate.
Event-driven message persistence. Instead of saving a conversation only after each full turn completes (and risking mismatches with model-provider message-formatting rules around tool calls and "thinking" blocks), Pattern now saves each event, such as user input, each model turn, and any mid-stream manipulation, as it occurs. This resolved recurring formatting errors and enabled mid-turn message injection and inline interactive UI.
Virtual file system. Pattern's VFS is a stateful workspace layer built on top of AgentCore's ephemeral compute sandbox. It is the team's own construction, not a native AgentCore feature (though AWS has since added comparable file-system configuration options to AgentCore Runtime). It gives the agent an in-memory place to read and write files using ordinary CLI tools (cat, grep, jq), without needing to invoke the Code Interpreter for trivial writes, and auto-copies into the sandbox whenever code executes. Per the presentations, the VFS is used to: push large tool output out of the context window, share file context with tools and sub-agents, and inject context at invocation time for the model to reference only if needed. The flow is bidirectional. A pre-execution phase packages and mounts relevant files from the VFS registry into the target micro-VM sandbox, and a post-execution sync extracts any newly generated or modified files back out to the VFS.
Large or page-specific datasets are handled the same way: serialized as files rather than injected into the model's context window, with the agent running simple lookup commands to see what's available and retrieve only what's relevant. Pattern noted the custom nature of their implementation also gives them portability to run components outside AgentCore entirely when needed, including with open-source models.

At the infrastructure level, Shaw described the flow as intentionally simple: a user or client request first passes through Bedrock AgentCore Identity, then into Bedrock AgentCore Runtime, which can call out to the Bedrock AgentCore Code Interpreter to execute code, persist conversation state to Postgres RDS for memory, and read and write durably to the virtual file system backed by Amazon S3.
The pattern is straightforward to implement on the frontend. A developer registers what's on the page, with a description and the underlying data, and the agent decides for itself whether it's relevant to a given question:
javascript
registerPageContext('category-growth', {
description: 'Category growth chart comparing brand revenue/unit growth against category',
params: { ... },
data: { ... },
})
registerPageContext('approvals', {
description: 'Pending approval items the user can act on.',
params: ...,
data: { ... },
})Nothing here is sent to the model by default. Instead, it's written out as an annotated JSON file in the virtual file system; if the agent decides the page context is relevant to what the user asked, it can use tools like jq or cat to pull just the piece it needs, avoiding context bloat entirely when the data isn't relevant.
Permissions model. Tool-level access mirrors existing product permissions (if a user can see something in the UI, the agent can access it on their behalf), with a secondary layer allowing specific actions to be marked as requiring explicit user approval before execution.
Evaluation and rollout. New tools and prompt changes are tested against internal "aspirational" and "core" evaluation sets before being promoted to production, with feature flags used to test changes against a subset of traffic first.
