Relayna logo Relayna

Inside the Relayna Tech Stack: Building a High-Performance HITL API with Elixir, Phoenix, and Ash

Red Lin 3 min read

When we started building Relayna, we knew we weren’t just building another “file upload” service. We were building a stateful workflow coordinator for AI agents.

AI agents move fast. They generate files, call tools, and make decisions in milliseconds. But the moment a human needs to step in, that speed hits a wall. To bridge this gap, we needed a stack that could handle thousands of concurrent agent requests, manage complex state transitions (pending → approved → webhook sent), and serve a polished, real-time UI to human reviewers—all while maintaining bank-grade security.

Here is the tech stack that makes Relayna possible.

The Foundation: Elixir and Phoenix

At the heart of Relayna is Elixir and the Phoenix Framework.

AI workflows are inherently concurrent. An agent might be polling for status while another is uploading a large PDF. Elixir’s lightweight processes (based on the Erlang VM) allow us to handle these simultaneous connections with negligible overhead. If one agent’s upload fails, it doesn’t affect the rest of the system.

Phoenix provides the high-performance web layer. But more importantly, Phoenix LiveView powers our reviewer pages. When an agent creates a “Checkpoint,” we generate a magic link. When the human opens that link, LiveView establishes a persistent connection. This allows us to show real-time updates (like an agent cancelling the request while the human is looking at it) without a single line of custom JavaScript or the complexity of a heavy frontend framework like React.

The Declarative Engine: Ash Framework

Relayna is built on the Ash Framework. If Elixir is the foundation, Ash is the architectural blueprint.

Ash is a declarative, resource-oriented framework for Elixir. Instead of writing imperative “controllers” and “services,” we define Resources (like Asset, Checkpoint, and ReviewLink). Each resource defines its own:

  • Attributes: What data it holds.
  • Actions: What it can do (e.g., :approve, :expire, :cancel).
  • Policies: Who can do what (crucial for our API key security).
  • Data Layer: In our case, PostgreSQL via ash_postgres.

By using Ash, we get a standard JSON:API implementation (ash_json_api) for free. When you call POST /api/checkpoints, you aren’t hitting a hand-rolled controller; you’re interacting with a highly optimized, policy-protected Ash action. This allowed us to focus 100% on the product logic rather than boilerplate API code.

Storage: Cloudflare R2 and Presigned URLs

A core feature of Relayna is “Secure File Relay.” AI agents upload sensitive files (invoices, PII-heavy reports, generated images) that humans need to see. We never wanted Relayna to be a “black box” for your data.

We chose Cloudflare R2 for our storage backend. R2 is S3-compatible, zero-egress, and highly reliable. But the real magic is in how we handle access: Presigned URLs.

When an agent requests an upload slot, Relayna generates a temporary Cloudflare PUT URL. The agent uploads directly to Cloudflare. The file bytes never touch our Phoenix server, which means we can handle 1GB files as easily as 1KB files. When a reviewer opens a page, we generate a temporary GET URL for the browser.

This “no-proxy” architecture ensures maximum performance and minimal data exposure.

Reliability: Oban and Durable Webhooks

When a human clicks “Approve,” your AI agent needs to know immediately. We use Oban for all background processing.

Oban is a persistent job queue for Elixir that lives inside our PostgreSQL database. When a decision is made, we don’t just “try” to send a webhook. we enqueue a SendWebhook job.

  • If your server is down? Oban retries with exponential backoff.
  • If the network hiccups? Oban logs the attempt and tries again.
  • Need to expire an asset after 24 hours? An Oban cron job handles the cleanup.

Because Oban is transactionally guaranteed with our database, we can guarantee that every decision results in an attempted notification.

The “Agent-Native” DX: OpenAPI Spex

Finally, we know that many of our “users” aren’t humans—they are other LLMs. Whether you’re using Claude Code, ChatGPT, or Cursor, those tools need to understand our API.

We use OpenApiSpex to generate our OpenAPI (Swagger) documentation directly from our Ash resources. This ensures that our documentation is always 1:1 with our actual implementation. You can point your AI coding tool at relayna.app/api/json/open_api and it will instantly know exactly how to integrate with us.

Conclusion

By combining the concurrency of Elixir, the declarative power of Ash, and the reliability of Oban, we’ve built a platform that is “agent-native” by design. Relayna isn’t just a wrapper; it’s a specialized piece of infrastructure built on the most robust stack available today.

Ready to add a human-in-the-loop to your agents? Get your API key today.