Skip to content

Case Study · AI Application Engineering

Ask A.J.
AI portfolio agent.

Ask A.J. is a production AI agent AJ designed and engineered to help recruiters and engineering leaders understand how he builds software, architects systems, and handles production tradeoffs.
The real Ask A.J. interface surrounded by its event stream, server architecture, knowledge sources, validation, and fallback behavior.
Live AI agentProduction-minded MVP

Overview

Ask A.J. demonstrates how AJ designs intelligent, resilient user experiences from product framing through server-side AI integration, streaming UI, safeguards, and graceful degradation.

It is not a generic chatbot. The browser receives an application-owned NDJSON event stream, while TanStack Start server code owns secrets, validation, model calls, fallback behavior, and structured logs.

How Ask A.J. Works

The implemented system is intentionally small: a React conversation interface, a TanStack Start server route, curated approved context, OpenAI Responses API streaming, layered fallbacks, and a server-side recruiter contact flow. Future RAG, vector search, LangGraph, MCP, and persistent conversations are roadmap items, not current claims.

Architecture flow

Request lifecycle

The successful path from recruiter question to streamed answer. The browser receives application events, not raw provider objects.

  1. Step 1

    Recruiter asks

    The React interface captures the question, preserves native form behavior, and supports Enter to send with Shift + Enter for a newline.

  2. Step 2

    Server validates

    The TanStack Start API route reads limited JSON, validates the request shape, checks origin, rate limits, and duplicate in-flight questions.

  3. Step 3

    Model streams

    Server code constructs approved instructions and context, calls the OpenAI Responses API with store:false, and translates provider deltas into NDJSON message.delta events.

  4. Step 4

    Interface renders

    The browser parses NDJSON, updates status and answer text progressively, handles aborts, and announces completion for assistive technology.

Architecture flow

Reliability and fallback flow

Before giving up, the server tries bounded recovery paths that keep user-facing errors safe and understandable.

  1. Step 1

    Request guards

    Content type, body size, schema, origin, rate-limit, and duplicate-request checks reject unsafe or noisy requests before provider work begins.

  2. Step 2

    Primary attempt

    The primary OpenAI model gets a bounded timeout and transient retries for retryable provider statuses before the first text delta.

  3. Step 3

    Fallback paths

    Eligible failures move to a fallback model, then curated cached answers, then a static graceful fallback if no cache match exists.

  4. Step 4

    Safe outcome

    Circuit breaker state, structured logs, safe user errors, and abort handling keep failures diagnosable without exposing secrets or raw provider internals.

Architecture flow

Contact delivery flow

Recruiter contact stays server-side, validates the form, and sends through Resend with the recruiter's email as reply-to.

  1. Step 1

    Recruiter submits

    The integrated contact form validates name, work email, optional role/company, message, and a hidden honeypot field.

  2. Step 2

    Server checks

    The contact API parses the payload, applies local rate limiting and duplicate-submission protection, and loads server-only email configuration.

  3. Step 3

    Resend delivers

    Resend sends from the verified server-owned sender to AJ's configured inbox with the recruiter's email set as replyTo.

  4. Step 4

    User sees status

    The UI shows accessible success or safe error messaging without exposing provider diagnostics or recruiter message content.

Why It Was Built This Way

The decisions below are visible in the current implementation: server-only provider calls, streamed NDJSON, bounded provider recovery, Storybook documentation, semantic tokens, and keyboard behavior that matches modern AI tools.

Keep model calls server-side

Why

Provider keys, instructions, request validation, token limits, and fallback behavior belong behind the TanStack Start boundary.

Tradeoff

The browser cannot call the model directly, so the server route has to own streaming translation and error handling.

Result

The client receives only application-owned stream events and never sees secrets, raw provider events, or protected instructions.

Stream NDJSON events

Why

A recruiter should see progress quickly, and the UI should own stable events rather than provider-specific payloads.

Tradeoff

The client must parse partial chunks safely and handle malformed stream events.

Result

Ask A.J. can show waiting, writing, completion, abort, and error states with one browser-facing contract.

Layer fallback behavior

Why

A credible AI product needs useful behavior when the primary provider path is slow, rate limited, or unavailable.

Tradeoff

Cached and static answers are narrower than live generation and must not pretend to be retrieval.

Result

The system can degrade from primary model to fallback model to curated answer to static fallback without fabricating citations.

Document interaction states in Storybook

Why

Streaming, waiting, error, aborted, long-content, mobile, and contact states are hard to reason about from a single happy path.

Tradeoff

Stories add maintenance overhead when the UI contract changes.

Result

The important visual states are deterministic, independently renderable, and safe from real network calls.

Use semantic success tokens

Why

The contact form success state should communicate completion without borrowing the site's coral-red accent or warning tone.

Tradeoff

The design token surface grows slightly.

Result

Success, error, accent, and neutral states now have clearer visual roles in light and dark themes.

Match modern AI keyboard behavior

Why

Enter to send and Shift + Enter for a newline are now expected in AI chat composers.

Tradeoff

Textarea key handling must respect native forms, pending states, and IME composition.

Result

Ask A.J. and the contact message textarea submit predictably while preserving multiline input and accessibility.

Designed Beyond the Happy Path

Response reliability

  • NDJSON streaming with stable application events.
  • Primary model timeout and transient retry before the first delta.
  • Fallback model for eligible provider failures.
  • Curated cached answers and static fallback response.
  • Circuit breaker for repeated provider failures.

Abuse and request protection

  • JSON content-type and 25 KB body limit.
  • Zod request schema with a 1,000-character question cap.
  • Allowed-origin validation.
  • Local per-client rate limiting.
  • Duplicate in-flight question protection.

Observability and diagnosis

  • Structured provider-safe logs for retries, fallback, circuit state, and request rejection.
  • Availability counters for valid request outcomes.
  • Provider diagnostics avoid API keys, authorization headers, full questions, and generated answers.

Interaction resilience

  • AbortController cancellation for Stop and replacement requests.
  • Safe user-facing errors for provider or configuration failures.
  • Duplicate contact submission protection.
  • IME-safe Enter behavior and disabled pending submit states.
  • Reduced-motion friendly loading status.

Interview the engineer

Meet the AI AJ built. Then meet the engineer behind it.

Start with Ask A.J. to explore AJ's work, architecture decisions, and engineering philosophy before the first conversation. The experience is both a recruiter tool and a working demonstration of his software judgment.

Start with Ask A.J.

Engineering Philosophy in the Product

Chase problems worth solving, not technologies

Ask A.J. starts from a recruiter problem: understanding AJ's judgment quickly. The model integration exists to serve that product moment, not to prove a tool choice.

AI should amplify engineering judgment

The model generates language, but the application owns validation, permissions, context, output limits, fallback behavior, and the user-facing contract.

Accessibility is product quality

The interface preserves labels, status announcements, keyboard submission behavior, reduced-motion support, safe focus return, and readable long-form answers.

Developer experience affects product quality

Storybook documents deterministic states for streaming, waiting, long content, mobile sticky behavior, contact success, validation, and error handling.

Reliability matters beyond the happy path

Retries, fallback model behavior, cached answers, static fallback, circuit breaking, rate limits, request guards, and safe errors are part of the current implementation.

Design systems are product infrastructure

AJ's enterprise design-system experience shows up in the portfolio platform through reusable components, semantic tokens, consistent states, and accessible interaction patterns.

Product Evolution

These are implementation milestones from the current repository and project notes, intentionally shown without fake dates.

  1. Milestone 1

    Recruiter-focused portfolio concept

    Ask A.J. became the flagship way to explore AJ's work, positioning, and engineering philosophy through a product experience.

  2. Milestone 2

    Streaming AI interface

    The UI gained NDJSON parsing, visible waiting and writing states, abort behavior, long-answer rendering, and follow-up conversation support.

  3. Milestone 3

    Server-side OpenAI integration

    Provider calls, instructions, output limits, retries, fallback model behavior, and safe provider errors moved behind TanStack Start server code.

  4. Milestone 4

    Production safeguards

    Request guards, rate limiting, duplicate protection, cached/static fallback answers, circuit breaking, and structured logging were added.

  5. Milestone 5

    Recruiter contact integration

    The contact form now validates locally and server-side, sends through Resend, and uses the recruiter's email as reply-to.

  6. Milestone 6

    Documentation and polish

    Storybook coverage, semantic success styling, mobile wrapper fixes, keyboard behavior, and this architecture case study make the product easier to inspect.

Engineering Signals

These are repository-verifiable signals, not live operational metrics. The product does not claim uptime, conversion, latency, token-cost, or accessibility scores that are not measured here.

Documented states
25Ask A.J. Storybook states across experience, status, answer content, launcher, and contact form stories.
Fallback layers
4Primary model, fallback model, curated cached answer, and static fallback response.
Architecture flows
3Request lifecycle, reliability/fallback flow, and contact delivery flow documented on this page.
Input modes
2Enter submits, Shift + Enter creates a newline, with IME composition respected.
Theme support
2Light and dark themes share semantic tokens for success, destructive, accent, and neutral UI states.
Validation gates
4Targeted ESLint, TypeScript, development build, and Storybook build are part of this sprint's validation.

Current System Architecture

React and TypeScript presentation components render the recruiter experience.

TanStack Start server routes own secrets, request validation, provider calls, and NDJSON framing.

The browser receives only application-owned stream events, never provider-specific events.

The contact form is server-only and sends through Resend with the recruiter's email as replyTo.

Implemented Capabilities

  • OpenAI Responses API integration
  • Configurable primary and fallback models
  • Server-owned system context
  • NDJSON streamed responses
  • Transient retry before the first text delta
  • Timeout budgeting
  • Circuit breaker
  • Curated cached answers
  • Static graceful fallback
  • Input validation
  • Origin validation
  • Local rate limiting
  • Duplicate request protection
  • Structured provider-safe logging
  • Token and cost controls
  • store:false so OpenAI does not retain response state for this feature

Reliability and Graceful Degradation

  • Primary OpenAI model
  • Bounded retry for transient provider failures before the first delta
  • One fallback OpenAI model
  • Cached answer for recognized common questions
  • Static graceful fallback when no cache match exists

Security and Abuse Safeguards

  • JSON-only request validation
  • 25 KB request body limit
  • 1,000-character current question limit
  • 500-token output cap
  • Allowed-origin validation
  • Local per-IP rate limiting
  • Duplicate in-flight request protection
  • No OpenAI tools, web search, file search, background calls, or client-side provider calls

Engineering Decisions and Tradeoffs

In-memory rate limits and circuit state are no-cost MVP safeguards, but they are per server instance.

Cached answers reduce failure impact for common questions, but they are not a replacement for retrieval.

The current knowledge source is curated content, not vector search or embeddings.

Current Limitations

  • No vector database, embeddings, LangGraph, MCP, or RAG retrieval is active yet.
  • Circuit-breaker, rate-limit, and availability counters are local to a server instance.
  • Functional availability is designed through graceful degradation, not guaranteed as an SLA.

Future Roadmap

  • Durable shared rate limiting and circuit state
  • RAG over AJ-owned portfolio content
  • Citation-backed answers
  • MCP tools for standardized capability access
  • Explicit workflow orchestration
  • Conversation persistence with privacy controls

Technology Stack

React 19TypeScriptTanStack StartTanStack RouterOpenAI Responses APINDJSON streamingTailwind CSS v4StorybookVercelResend
Ask A.J.