From Learning Project to Managed Platform: How Ethyx Found Its Shape

David Crush | Aug 22, 2026 min read

I didn’t start Ethyx with a product thesis. I started it to learn.

The first idea was deliberately narrow: a thin proxy in front of backend LLMs so my side projects could share one API interface regardless of whether the model was OpenAI, Anthropic, or xAI. Adapters, a model catalog, streaming normalization—utilities to make swapping providers easier. Not yet a company. Not yet a moat.

A few months later, I wrote about what Ethyx became on the architecture side: lock-in is an architecture problem, and the answer is a queued, provider-agnostic chat turn with DB-backed SSE. That post is the technical spine. This one is the product story—how a learning project became a managed multi-model workspace, and why I stopped building a BYOK proxy along the way.

I was not going to out-execute the proxies

As I built, an honest question kept surfacing: “unify provider APIs behind one client” is already solved well.

ApproachExampleStrength
Self-hosted OSSLibreChatFree, full control, you manage keys and ops
Client-side BYOKTypingMindKeys stay with you; you manage billing at each provider
Browser comparisonChatHub and othersSide-by-side multi-model replies in one tab

LibreChat is excellent if you want to self-host and own the stack. TypingMind is strong if you want BYOK control without running infrastructure. ChatHub-style tools are great for quick model comparisons. I was not going to out-execute them at being a proxy or key vault.

That realization was clarifying, not discouraging. The proxy layer was my on-ramp to understanding provider APIs, streaming shapes, tool formats, and attachment rules. It was never the durable product.

The gap I actually cared about

What I did not find was a managed service in this shape:

  • Call paid APIs through one account without maintaining N provider dashboards, SDK quirks, and billing relationships
  • A provider-agnostic workspace—history, projects, tools—where you can switch model and provider without starting over in another product
  • Platform-owned tools that work the same whether the turn runs on Claude, GPT, Gemini, or Grok

The inconvenience is real. Each provider has different APIs, streaming event shapes, tool schemas, attachment rules, and model lifecycles. Setting that up once for yourself is fine. Productizing it so non-engineers benefit—and so the integration layer compounds over time—is the hard part.

Ethyx was born to fill that void. Not to be “another API gateway,” but a managed multi-model workspace where integration is the product.

flowchart TB
  subgraph origin [Phase1_Origin]
    Proxy[ThinProviderProxy]
    Utils[SwapModelsUtilities]
  end
  subgraph market [ExistingSolutions]
    LibreChat[LibreChat_SelfHosted]
    TypingMind[TypingMind_ClientBYOK]
  end
  subgraph gap [GapIdentified]
    Managed[ManagedMultiModelWorkspace]
    Tools[PlatformAgnosticTools]
  end
  subgraph evolution [EthyxEvolution]
    BYOK[v1_BYOK]
    Pivot[v1_2_SubscriptionPivot]
    Retire[July2026_FullBYOKRemoval]
    Platform[OperatorKeys_Orchestration]
  end
  Proxy --> market
  market --> gap
  gap --> evolution
  BYOK --> Pivot --> Retire --> Platform

The BYOK era: what it proved

Ethyx v1.0 shipped provider-agnostic chat with bring-your-own-key. Users stored encrypted provider credentials; Ethyx handled SDK differences behind a unified interface. The original product requirements were explicit: no Ethyx-hosted keys yet. BYOK was the access model.

It worked as a technical proof. The adapter pattern held. I could route a turn to Anthropic Messages, OpenAI Completions or Responses, Gemini, or an OpenAI-compatible endpoint—and normalize enough of the surface that the UI didn’t care which vendor was answering.

What BYOK did not solve:

  • Billing and onboarding. Every new user needed accounts at multiple providers, working API keys, and enough context to debug rate limits alone.
  • Support burden. Misconfigured keys, expired credits, and provider-side errors landed on Ethyx support threads even when the product was fine.
  • Product coherence. Usage visibility, tool gating, search modes, and subscription tiers all assume a single operator key plane where Ethyx controls upstream access consistently.

BYOK taught me that unifying APIs is table stakes. The bet worth making was everything wrapped around the call: workspace, tools, workflows, and the glue between vendors.

There was a subtler lesson too. BYOK users tended to be engineers who already understood API keys. That was my audience at the time, but it wasn’t the audience for a managed workspace product. Non-engineers don’t want to create four provider accounts before their first chat. They want to pick a model, ask a question, and have the plumbing work. BYOK was a bridge I needed to cross—not a destination.

The pivot: operator keys, subscriptions, and full BYOK removal

The transition happened in phases—not a single flip.

Early 2026: Operator-managed ETHYX_APP_{PROVIDER}_KEY credentials shipped alongside BYOK, with hasAiAccess() gating who could use AI features at all. Preview users, subscribers, and staff could access models through Ethyx’s keys while BYOK still existed in the codebase.

v1.2 (May 2026): A positioning pivot. Subscription-first story, Stripe closed-test billing, promo codes, Google Drive integration. BYOK retired from product narrative even before the code caught up. I wrote about that release on the Ethyx blog.

July 2026 (PR #335): Full BYOK removal. The user_provider_credentials table, provider-credentials APIs, and related UI were deleted. All upstream access is now operator-managed keys gated by account tier.

Today, users access models via Ethyx subscription or granted AI access (Preview, Subscribed, Staff, and similar tiers)—not personal provider API keys. A distinction worth keeping straight: Ethyx public API keys (for programmatic access to Ethyx’s own API) still exist. That is not BYOK. Closed beta and invite-code access are accurate to say today; public checkout remains behind feature flags while billing models settle.

Why retire BYOK beyond positioning?

  • Support: Users blamed Ethyx for provider-side failures they owned alone.
  • Coherence: Tools, workflows, usage metering, and billing assume one key plane.
  • Privacy story shift: Layer 1 is Ethyx operator credentials—not your personal ChatGPT login. Layer 2 is pseudonymized identity metadata restored in the stream. I summarized that honestly on Ethyx in Your name never reaches the model. Pseudonymization is not anonymization. Prompts still reach upstream models for inference. We do not have provider zero-data-retention agreements, and I won’t claim otherwise.

The two-phase removal mattered. Shipping operator keys while BYOK still existed let me validate billing, usage metering, and support workflows before deleting the old path. Users who relied on personal keys had time to migrate. Engineering could delete dead code without a rushed cutover. Product narrative and implementation diverged for a few months—that was intentional friction, not drift.

Architecture choices: hexagonal boundaries

The product pivot didn’t replace the technical thesis—it sharpened it.

Providers are building walled tool gardens: native connectors, MCP directories, built-in search. Users who invest there get locked to that vendor. Ethyx inverts the bet:

The user’s tools and knowledge live in the Ethyx ecosystem while the model stays a swappable commodity.

That line comes straight from internal vision docs, and it still guides tradeoffs.

Ethyx uses pragmatic hexagonal boundaries:

  • Ports: ChatProviderAdapter contract
  • Adapters: OpenAI (including dual endpoints), Anthropic Messages, Gemini, OpenAI-compatible providers (xAI, DeepSeek, Kimi, Perplexity)
  • Routers: ProviderRouter, WebSearchToolRouter, ImageProviderRouter
  • Orchestration: ChatStreamManager, PersistedChatTurnService, ChatToolDispatcher

Bounded contexts stay separated: Chat, Images, Search, Auth/MFA, Catalog. Search and Images don’t depend on Chat adapters except shared primitives.

flowchart TB
  http[HTTP_Controllers] --> services[Application_Services]
  services --> orchestration[ChatStreamManager_ToolDispatcher]
  orchestration --> router[ProviderRouter]
  router --> adapters[ChatProviderAdapter_implementations]
  adapters --> upstream[OpenAI_Anthropic_Gemini_xAI_etc]

Controllers never call vendor HTTP directly. That rule sounds obvious until you’ve debugged a streaming regression at 2 a.m. because one code path bypassed the adapter. The turn lifecycle—enqueue, worker, DB progress writes, SSE tail to the browser—is covered in depth in the first post in this series. The simplified mental model:

User → POST /chat/turns → Queue worker → ChatStreamManager
  → ProviderRouter → Adapter (stream) + Tool rounds
  → PostgreSQL progress writes
Browser ← SSE tail ← polls DB

Three connections, not one long vendor socket. The browser tails Ethyx’s store, not OpenAI’s stream handle.

Why hexagonal boundaries instead of a monolith that “just calls OpenAI”? Because every provider quirk becomes a localized change. When Anthropic ships a new streaming event type, I touch the Anthropic adapter—not the controller, not the React composer, not the tool dispatcher. When we add a new OpenAI-compatible host, it’s a new adapter class plus catalog entries, not a fork of the chat stack.

The same separation applies upstream of chat. Image generation routes through ImageProviderRouter. Web search routes through WebSearchToolRouter with Tavily depth controlled per mode. Those contexts share auth and primitives but don’t entangle their adapter graphs. That’s how you keep a small team from drowning in cross-cutting regressions.

Integration is the moat

Unifying chat completions behind a REST facade is a weekend project. Owning the integration pain across providers, tools, attachments, and streaming privacy—that’s where compound value lives. A few vignettes from production:

OpenAI has two streaming surfaces

Chat Completions (messages) and Responses (input) are not interchangeable. Some catalog models are Responses-only; routing to the wrong endpoint returns a 404 that looks like Ethyx is broken. Ethyx gates per model in the catalog and adapter layer so the router picks the right surface before the worker opens a stream.

Attachments differ by vendor and endpoint

Images vs PDFs, Completions vs Responses attachment shapes, models that accept documents vs models that don’t—the catalog and validation layer filter what each turn can carry. A user shouldn’t have to learn provider matrix rules to attach a file.

Tool schema normalization

Anthropic wants tool_choice: none after tool rounds. Gemini uses functionCallingConfig. Some turns need an answer-only synthesis pass after research tools finish. The dispatcher normalizes function schemas per vendor so platform tools—web search, Wikipedia, calculate, Google Drive reads, parallel research in Expert mode—execute once against Ethyx’s contract.

flowchart LR
  model[Model_streams] --> toolCall{Tool_call}
  toolCall -->|yes| exec[Ethyx_executes_tool]
  exec --> result[Tool_result]
  result --> model
  toolCall -->|no| done[Turn_completes]
  exec -->|failure| graceful[Graceful_degradation]
  graceful --> model

Tool failures never fail the turn. The model gets an error-shaped result and continues—or the UI shows partial progress. That resilience matters when you’re fanning out parallel research tracks in Expert mode.

Auto model selection and per-turn choice

model=auto resolves per turn via heuristics and a nano classifier, with sticky continuity inside conversations and attachment-aware filtering. Users can also pick a concrete model in the composer for a given turn. Message-level switching is a real product capability; it’s not marketing fluff.

The classifier isn’t magic—it’s a lightweight intent bucket (coding, research, creative, general) that maps to catalog entries with cost and capability constraints. Sticky continuity means a conversation doesn’t thrash between providers turn to turn unless the user asks for it. Attachment-aware filtering excludes models that can’t handle what you’re sending. These heuristics are product decisions as much as engineering ones.

Per-turn search modes

Quick, Balanced, and Expert aren’t cosmetic labels. They change which tools are available, how deep Tavily search goes, whether Claude effort escalates, and whether Expert’s parallel research fan-out runs. A user picks a mode per turn the same way they pick a model—one workspace, different depth of orchestration behind the same composer.

That only works when Ethyx owns the key plane. BYOK users with their own rate limits and provider entitlements made uniform mode behavior nearly impossible to guarantee. Operator keys let us negotiate consistent tool access and present a coherent product surface.

Streaming pseudonymization

Identity metadata—name, email, filenames—can be pseudonymized before the provider call and restored in the outbound stream. That’s harder than one-shot APIs where you transform input once. Streaming means token-by-token restoration without leaking placeholders to the user. The model still receives your prompt content for inference; we’re honest about that boundary. What we reduce is incidental PII in metadata that doesn’t need to cross the wire.

These are not features you bolt on after the proxy works. They are the product. Every vignette above is a reason someone pays for a managed client instead of wiring their own LiteLLM instance and calling it done.

Who this is for—and who should use something else

I’m not trying to convince everyone to leave LibreChat or TypingMind. They solve real problems well. Ethyx is for people who want a managed workspace with integration depth, not another place to paste API keys.

LibreChat / self-hostTypingMind BYOKEthyx managed
Who holds provider keysYouYou (client-side)Ethyx (operator)
Ops burdenHigh (host, update, keys)Medium (N provider accounts)Low (one Ethyx account)
Multi-model workspaceVariesVariesCore product
Prompts to upstreamYesYesYes
Claim zero retentionNoDepends on setupNo — stated plainly

If you want maximum control and you’re willing to run infrastructure, self-host. If you want keys to never touch a server you don’t trust, client-side BYOK products are a strong pattern—see Ethyx’s TypingMind comparison for how we think about the tradeoff without pretending we’re the same product.

If you want one account, shared tools and history across providers, and someone else to maintain the adapter matrix—Ethyx is aimed at you. We’re still in closed beta; invite codes are the front door today.

More product context lives on ethyx.ai, the FAQ, and the model catalog.

What I learned—and where Ethyx is headed

Building Ethyx as a learning project was the right call. It forced me to understand provider APIs deeply enough to know what “unify behind one client” actually costs—and to see that the proxy layer was the shallow end of the pool.

The durable insight: future innovation is not only bigger models. It’s how we call and integrate with them. Ethyx is betting on provider-agnostic orchestration—message-level model choice, a shared tool catalog, durable workflows, compare mode, and observability (turn timing, tool metadata) as the moat. Not on being the cheapest proxy.

We’re in a v1 stabilization freeze on new chat tools: measure what we have before growing the catalog. That’s engineering maturity, not stagnation. The adapter layer, turn pipeline, and tool platform are the foundation; what sits on top should earn its complexity.

If you’re a technical leader weighing build vs buy in this space, I hope this helps. The market has excellent proxies and excellent BYOK clients. The gap I cared about was a managed multi-model workspace where integration is the product—and that’s the shape Ethyx grew into.

Ethyx is in closed testing at ethyx.ai. Follow the build, request an invite, or read the architecture post if you want the turn-pipeline deep dive next.