ADR-018: Remove AI SDK, use openai SDK directly with hub-own streaming
Replace the Vercel AI SDK with direct OpenAI SDK calls and a custom AgentLoop. The AI SDK has zero runtime integration today, so removing it costs nothing. Supply chain risk (2-5 releases/day, April 2026 Vercel breach, bus factor of 1) makes it a liability we don't need. Key changes: - ADR-018 accepted: openai package (zero runtime deps) replaces ai SDK - AgentLoop handles multi-step tool execution explicitly (~300 LOC vs AI SDK's ~2700 LOC streamText) - Hub owns UIMessage/UIPart/ToolCallState types (extends ADR-016) - Hub owns streaming protocol (subset of AI SDK's UIMessageChunk wire format with step boundaries, error handling, usage tracking) - operationToOpenAITool() maps TypeBox schemas directly, no adapter - Trade-off: ~1100 LOC total new code for the savings of 6+ transitive deps, supply chain risk, and release cadence coupling Updates AGENTS.md constraints and dependencies, adds OQ-63/OQ-64/OQ-65 and Theme 11 (Inference & LLM Integration) to open questions.
This commit is contained in:
@@ -28,6 +28,7 @@ Cross-cutting compilation of all unresolved questions across the hub architectur
|
||||
| 8. Deployment & Operations | OQ-34–OQ-37 | Migrations, hot spare, observability, Redis topology |
|
||||
| 9. Cross-Cutting Implementation Gaps | OQ-38–OQ-50 | Startup, config, logger, Gitea, keypal, auth, schemas |
|
||||
| 10. Future / Low Priority | OQ-51–OQ-60 | Phase 3+, memory, versioning, visualization |
|
||||
| 11. Inference & LLM Integration | OQ-63–OQ-65 | Streaming protocol, SDK choice, part persistence |
|
||||
|
||||
### Resolved by ADRs
|
||||
|
||||
@@ -37,6 +38,7 @@ Cross-cutting compilation of all unresolved questions across the hub architectur
|
||||
| [ADR-015](../decisions/ADR-015-dev-spoke-not-opencode.md) | OQ-16, OQ-17, OQ-26, OQ-28, OQ-51, OQ-55 |
|
||||
| [ADR-016](../decisions/ADR-016-hub-own-schema.md) | OQ-18, OQ-19 (confirmed) |
|
||||
| [ADR-017](../decisions/ADR-017-hub-first-roles.md) | OQ-26, OQ-28, OQ-51 (overlaps with ADR-015) |
|
||||
| [ADR-018](../decisions/ADR-018-no-ai-sdk-direct-openai-proxy.md) | OQ-16 (extended to TypeScript types) |
|
||||
|
||||
---
|
||||
|
||||
@@ -537,6 +539,34 @@ Cross-cutting compilation of all unresolved questions across the hub architectur
|
||||
|
||||
---
|
||||
|
||||
## Theme 11: Inference & LLM Integration
|
||||
|
||||
### OQ-63: What is the exact subset of UIMessageChunk types the hub proxy emits?
|
||||
|
||||
- **Origin**: [ADR-018](../decisions/ADR-018-no-ai-sdk-direct-openai-proxy.md)
|
||||
- **Status**: open
|
||||
- **Priority**: medium
|
||||
- **Question**: ADR-018 defines an initial subset of AI SDK's UIMessageChunk protocol for the hub's SSE streaming format. The initial set covers text, reasoning, tool call lifecycle, step boundaries, and error events. As features are added (e.g., source URLs, file attachments, dynamic tools), new chunk types need to be specified. Should the hub define a formal schema for its streaming protocol, or document it informally? How do we version the protocol if chunk types change?
|
||||
- **Cross-references**: OQ-64 (raw HTTP vs SDK streaming)
|
||||
|
||||
### OQ-64: Should the direct agent use the openai SDK's streaming API or raw HTTP?
|
||||
|
||||
- **Origin**: [ADR-018](../decisions/ADR-018-no-ai-sdk-direct-openai-proxy.md)
|
||||
- **Status**: open
|
||||
- **Priority**: low
|
||||
- **Question**: The direct agent path can use the `openai` SDK's typed streaming API (`client.chat.completions.create({ stream: true })`) or raw HTTP for more control over SSE parsing. The SDK provides convenience (typed responses, automatic tool call accumulation) but adds abstraction. The proxy path must use raw HTTP (Hono SSE handler). Should both paths use the same approach for consistency, or is it acceptable to use the SDK for the direct agent and raw HTTP for the proxy?
|
||||
- **Cross-references**: OQ-63 (streaming protocol)
|
||||
|
||||
### OQ-65: What is the buffered write strategy for part persistence?
|
||||
|
||||
- **Origin**: [ADR-018](../decisions/ADR-018-no-ai-sdk-direct-openai-proxy.md)
|
||||
- **Status**: open
|
||||
- **Priority**: medium
|
||||
- **Question**: Streaming LLM responses produce many part updates (text deltas, state transitions, tool call results). Writing each delta as a separate database write would be extremely expensive. Options: (a) flush on `*-end` events (per-part commits — text parts committed when done, tool parts committed when complete), (b) flush on `step-finish` (per-step commits — all parts in a step committed together), (c) flush on `finish` (per-message commits — all parts committed when the agent turn is complete). Per-part (a) balances latency and write volume best for real-time SSE updates.
|
||||
- **Cross-references**: OQ-63 (streaming protocol defines when `*-end` events fire)
|
||||
|
||||
---
|
||||
|
||||
## Cross-Cutting Dependencies
|
||||
|
||||
These questions block each other or share resolution paths:
|
||||
@@ -551,7 +581,7 @@ These questions block each other or share resolution paths:
|
||||
|
||||
5. **Data Lifecycle Chain**: OQ-12 → OQ-13 → OQ-14 — Operation deletion strategy, call graph retention, and payload truncation interact. OQ-12 determines whether operations can be removed at all.
|
||||
|
||||
6. **Dev Spoke Chain**: OQ-61 → OQ-62 → OQ-06 — Dev spoke operations and distribution need specification before spoke provisioning can be fully designed. OQ-11 is narrowed by ADR-015 but not resolved.
|
||||
7. **Inference Chain**: OQ-63 → OQ-64, OQ-65 — The streaming protocol subset (OQ-63) determines what the direct agent and proxy need to produce. The SDK vs. raw HTTP choice (OQ-64) and the persistence strategy (OQ-65) depend on the protocol definition.
|
||||
|
||||
---
|
||||
|
||||
@@ -621,6 +651,9 @@ These questions block each other or share resolution paths:
|
||||
| OQ-60 | Full ujsx call templates | call-graph | low | open |
|
||||
| OQ-61 | Dev spoke operations | ADR-015 | medium | open |
|
||||
| OQ-62 | Dev spoke distribution and config | ADR-015 | medium | open |
|
||||
| OQ-63 | Hub proxy SSE chunk type subset | ADR-018 | medium | open |
|
||||
| OQ-64 | Direct agent: openai SDK vs raw HTTP | ADR-018 | low | open |
|
||||
| OQ-65 | Part persistence buffered write strategy | ADR-018 | medium | open |
|
||||
|
||||
### High Priority Open Questions (Blocking)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user