IBEX Harness
DocsBenchmarksBlogChangelogRoadmap
GitHub
IBEX Harness

Documentation

Architecture Decision RecordsADR-0002: Repository foundation bootstrapADR-0003: Branch protection and merge policyADR-0004: Protobuf and code generation policyADR-0005: Postgres migration strategyADR-0006: Auth protobuf contract (`ibex.auth.v1`)ADR-0007: Auth token validation implementationADR-0008: Security scanning and CI quality gatesADR-0009: Permission bitmap layoutADR-0010: Cryptography policyADR-0011: Proxy auth gRPC client and middlewareADR-0012: Proxy request normalization (OpenAI chat)ADR-0013: Proxy input validation and stable error envelopeADR-0014: Core domain migration sequencingADR-0015: Proxy rate limit skeleton (Phase 1)ADR-0016: Proxy agent identity verification (Phase 1)ADR-0017: Request ID and trace context strategy (Phase 1)ADR-0018: Graceful shutdown contract (Phase 1)ADR-0019: OpenTelemetry provider configuration (Phase 1)ADR-0020: Shared package boundaries — `packages/config` and `packages/apierror`ADR-0021: Prometheus Metric Catalog (Phase 1)ADR-0022: Health check contract (Phase 1)ADR-0023: Docs site architecture (Phase 1.5)ADR-0024: Benchmark data publishing modelADR-0025: LLM provider abstractionADR-0026: OpenAI client designADR-0027: Streaming dual-write strategyADR-0028: Auth cache designADR-0029: Token revocation propagation via Redis pub/subADR-0030: Directive versioning strategyADR-0031: System prompt injection strategyADR-0032: Session data model and retentionADR-0033: ClickHouse llm_traces schema and retentionADR-0034: Proxy overhead performance measurement methodologyADR-0035: Chat Idempotency-Key Redis dedupeADR-0038: Context assembly service design and gRPC contractADR-0039: Proxy Postgres ownership for session and directive storesADR-0040: Anthropic provider adapterADR-0041: Model capability registryADR-0042: Self-hosted OpenAI-compatible LLM adapterADR-0043: Tokenizer registry architectureADR-0044: Non-streaming response pipelineADR-0045: Streaming response transformationADR-0046: Embedder interface and profile registryADR-0047: Memory temporal validity foundationADR-0048: Memory multi-label categoriesADR-0049: Memory relationship graph readinessADR-0050: MCP server skeleton (transport, auth, audit)ADR-0051: Local LGTM observability stack (Phase 2.5 exit pull-forward)ADR-0052: Memory schema v2 expand (HNSW, quality columns)ADR-0053: Vector store abstraction and composite scoring v2ADR-0054: In-process Presidio PII detection in memoryADR-0055: Memory write-path exact and near-duplicate dedupADR-0056: Temporal-interval-aware conflict detectionADR-0057: Memory write-path persistence and orchestrationADR-0058: Semantic search FTS fallback triggerADR-0059: Hot cache read pathADR-0060: Memory service tenant isolation architectureADR-0061: Retrieval-quality benchmark methodologyADR-0062: Worker task observability and dead-letter handlingADR-0063: Extraction output schema v2ADR-0064: Extraction provider registry and batch executionADR-0065: Extraction batch idempotency and turn pointer orderingADR-0066: Extraction quality evaluation harnessADR-0067: Context capability catalog generate-and-diff for token budgetsADR-0068: Composite scoring-time relevance gateADR-0069: Context packer bounded DP knapsackADR-0070: Context formatting locked ordering and session nonceADR-0071: Context assembly gRPC degradation ladder and retrieval deadlineADR-0072: Extraction enqueue via worker HTTP (not Celery Redis wire format)ADR-0073: Organization Lifecycle and Cascading SuspensionADR-0074 Provider Credential StorageADR-0075 Per-Org Model Routing PolicyADR-0076: Circuit Breaker per ProviderADR-0077: Provider Fallback RoutingADR-0078: Operator runtime topology & environment contract (4.P.0)ADR-0079: Operator session RS256 dual-verify and TOTP step-upIBEX Console service rename and boundaryADR-0081: Fail-closed Proxy runtime controlsD2 metadata-only trace read contractD2 publication, identity, query, and lifecycle contract
ADRs›ADR-0064: Extraction provider registry and batch execution
ADRs

ADR-0064: Extraction provider registry and batch execution

Architecture decision record 0064 — cost-tiered OpenAI/vLLM extraction, session-close batching, ClickHouse llm_traces, and confidence policy.

ADR-0064: Extraction provider registry and batch execution

  • Status: Accepted
  • Date: 2026-09-03
  • Authors: IBEX Harness team
  • Milestone: 3.5.B.2 Cost-tiered extraction execution
  • Depends on: ADR-0063, ADR-0020, ADR-0032

Context

3.5.B.1 shipped the extraction JSON contract in the worker (PR #680 / 078d837). B.2 must call a real LLM, write memories, and record token usage without:

  • importing Go packages/provider or services/memory (ADR-0020)
  • stacking @traced_task on Celery (spans already wrap IbexTask.__call__)
  • inventing pending_review on memories.status
  • loading turn text from checkpoints (hashes only, ADR-0032)
  • citing ADR-0036 (that number is unpublished)

No GPU/vllm runner exists in CI (ubuntu-latest only).

Decision

1) Provider ABC in the worker

ExtractionProvider exposes name, supported_models, and extract(system, user) -> ExtractionCall (raw JSON + usage). OpenAI and vLLM share one OpenAI-compatible HTTP client (httpx). vLLM omits Authorization when the key is empty.

Registry is startup-once, keyed by openai | vllm (IBEX_WORKER_EXTRACTION_PROVIDER / EXTRACTION_PROVIDER), fail-closed: openai without OPENAI_API_KEY raises; vllm without IBEX_WORKER_EXTRACTION_BASE_URL raises. No stub fallback.

Default cloud model is gpt-4o-mini (still listed on OpenAI’s public API pricing as of 2026-09-03). Default vLLM model is Qwen2.5-14B-Instruct; operators may substitute Qwen2.5-7B-Instruct when 14B VRAM does not fit. Manual verification only — not run in CI.

2) Confidence policy (a)

Extraction confidence is recorded on the memory row; it does not gate persistence or invent a review status (ADR-0056/0057).

Overall ExtractedMemory.confidence is forwarded as POST /v1/memories confidence. Safety remains Track C (PII, dedup, temporal conflict).

3) Taxonomy duplication

Worker VALID_LABELS stays local. If migration 000015 / memory VALID_LABELS changes, update services/worker/app/extraction/schema.py in the same PR (issue #681).

4) Batch task and turn source

Task ibex.worker.extraction.extract_session_memories (queue=extraction, IbexTask, soft/hard 120/180s). autoretry_for is transport/5xx (ExtractionTransportError) only. org_id is required in kwargs.

Turns arrive in the payload (turn_index, role, content) because checkpoints have no message text. Payload archival is still missing (ADR-0032). Postgres SessionStore is mandatory for extract_session_memories (fail closed without database_url): SELECT/UPDATE ibex_core.sessions with explicit org_id + RLS GUC; skip turn_index <= last_extracted_turn; require status=completed and deleted_at IS NULL. After each turn's HTTP writes succeed, non-atomic UPDATE last_extracted_turn = GREATEST(...) for that turn (not a shared cross-service transaction). Identity-based idempotency keys and crash-window semantics are resolved by ADR-0065 in 3.5.B.3.

Batch JSON: BatchExtractionResult / TurnExtraction. Prompt is EXTRACTION_SYSTEM_PROMPT_V2 plus a batch suffix. Single-turn uses turns length 1.

5) Memory HTTP temporal fields

CreateMemoryRequest gained optional valid_from / valid_until (already on CreateMemoryCommand). Mapping is pass-through. org_id is never accepted in the body.

6) ClickHouse llm_traces

Worker HTTP insert uses the same columns as Go TraceRecord. org_id is required (refuse). Never store prompt/completion. Empty CLICKHOUSE_DSN skips insert and increments ibex_worker_extraction_clickhouse_skip_total. httpx is used instead of clickhouse-connect so LLM mocks and CH mocks share one HTTP stack; stdlib urllib lacks MockTransport and first-class timeout typing.

7) Cost estimate (dated, not ADR-0036)

OpenAI public prices for gpt-4o-mini as of 2026-09-03: $0.15 / 1M input tokens, $0.60 / 1M output tokens. A representative 10-turn session-close call (~1.2k input + 400 output) is about $0.00042 — same order of magnitude as the old “$0.0008/10-turn” sketch, not a guarantee.

Consequences

  • Extraction HTTP stays in the worker (no packages/ Python LLM library).
  • Operators must enqueue turns in the task payload until archival exists.
  • vLLM quality is operator-verified; CI only mocks HTTP.
  • httpx is a justified worker dependency (timeouts + MockTransport).

Was this page helpful?

Edit on GitHub

Last updated on

PreviousADR-0063: Extraction output schema v2NextADR-0065: Extraction batch idempotency and turn pointer ordering

On this page

  • Context
  • Decision
  • 1) Provider ABC in the worker
  • 2) Confidence policy (a)
  • 3) Taxonomy duplication
  • 4) Batch task and turn source
  • 5) Memory HTTP temporal fields
  • 6) ClickHouse llm_traces
  • 7) Cost estimate (dated, not ADR-0036)
  • Consequences
0%