Skip to content

feat(api): add per-request configuration overrides - #1333

Closed
Kevin0811 wants to merge 10 commits into
TauricResearch:mainfrom
Kevin0811:feat/api-config-overrides
Closed

Kevin0811 wants to merge 10 commits into
TauricResearch:mainfrom
Kevin0811:feat/api-config-overrides

Conversation

@Kevin0811

Copy link
Copy Markdown

Summary

Add comprehensive per-request configuration override support to the TradingAgents API.

  • Add ConfigOverrides schema for type-safe per-request config
  • Implement resolve_overrides service to handle research_depth presets (shallow/medium/deep)
  • Add /api/config endpoint to list available configuration options
  • Enhance DecisionService with improved markdown parsing for ratings and price fields
  • Support explicit override precedence (explicit round counts win over presets)
  • Comprehensive test coverage for config resolution, decision parsing, and dependencies

Test plan

  • All new test files pass (test_api_config_overrides.py, test_api_decision_service.py, test_api_dependencies.py, test_api_router_config.py)
  • Existing tests pass with schema updates (test_api_routers_analyze.py)
  • Config override resolution works for both AnalyzeRequest and TaskCreateRequest
  • Research depth presets expand correctly (shallow→1, medium→3, deep→5 rounds)
  • Explicit round counts take precedence over presets
  • Passthrough fields (llm overrides, max_tokens, etc.) work correctly

🤖 Generated with Claude Code

Kevin0811 and others added 10 commits September 12, 2026 16:37
- Introduce a dedicated API service using a multi-stage Dockerfile and update docker-compose to expose port 8000.
- Implement standalone execution functions for market and sentiment analysts to enable independent, programmatic analysis.
- Update .dockerignore to exclude cache files and add invoke to dev dependencies for improved task automation.
- Reorganize the API codebase to enforce separation of concerns using Clean Architecture principles.
- Introduce dedicated layers for core error handling, domain business logic (entities, services, repositories), infrastructure implementations (LLM, agents, state storage), and interface components (routers, schemas).
- Centralize all public exports in __init__.py with comprehensive docstrings and update app initialization to register global exception handlers.
- Add TaskManager for in-memory tracking, request deduplication, and TTL-based cleanup.
- Implement TaskService to orchestrate asynchronous analysis execution by wrapping the existing AnalysisService.
- Update API exports and dependency injection to support the new workflow, enabling non-blocking task submission, lifecycle management, and status retrieval.
- Add tests for FastAPI app factory covering config overrides, health checks, versioned OpenAPI routes, lifespan initialization, and router registration.
- Add tests for TaskManager verifying task creation, status transitions, and request deduplication logic.
- Improve coverage for core API components to prevent regressions during future development and refactoring.
- Modify `TaskManager` to only clean up stale pending tasks when TTL is enabled (`self._ttl > 0`).
- Introduce a new `test-api` invoke task to run only API-related tests using the `test_api` pytest keyword marker.
- Update the `task` import to use the explicit `invoke.tasks` path for better clarity.

This prevents freshly created tasks from being removed in test scenarios where TTL is set to 0.
The /data endpoints called the agent data tools as plain functions with
invented signatures, so every one of them failed at runtime or silently
returned a vendor error string with HTTP 200. The tools are LangChain
StructuredTools, and their real parameters (date windows, freq, topic,
FRED series) never matched the schemas the API advertised. This reworks
the service layer to invoke the tools correctly and to return structured
records instead of opaque CSV blobs.

Key changes:
- Call every data tool via .invoke({...}) with its documented argument
  names, replacing positional calls that landed values in wrong slots
- Add domain/vendor_reports.py to parse vendor OHLCV CSV and indicator
  reports into typed rows, series and points
- Translate vendor failures into typed API errors, including the
  NO_DATA_AVAILABLE / DATA_UNAVAILABLE prose sentinels the routing layer
  returns for agent consumption; export those as constants in
  dataflows/interface.py so both sides cannot drift
- Replace the ticker-scoped prediction-markets route with topic search,
  and split global news out of /news into its own /global-news endpoint
- Repoint macro indicators from a country code to a FRED series alias or
  raw series ID with a trailing window
- Correct IndicatorName to the exact keys both vendors accept, drop the
  unused Country enum, and add ReportFreq plus look_back_days/limit
  parameters across the request schemas
- Add bare_crypto_to_pair so the API alone reads a bare BTC as the coin,
  leaving normalize_symbol's equity-safe behaviour untouched
- Cover the routes, report parsing and schemas with new tests

BREAKING CHANGE: /data/prediction-markets/{ticker} is now
/data/prediction-markets?topic=..., /data/macro-indicators takes
`indicator` instead of `country`, /data/news drops `country` in favour of
/data/global-news, and the stock and indicator responses return records
instead of CSV strings.
Long analyses ran via BackgroundTasks with a blocking semaphore, so queued
tasks occupied AnyIO threadpool slots and starved request handling.

- add TaskWorker, a bounded ThreadPoolExecutor that queues excess tasks
  without holding threads, and log exceptions that die in the Future
- own TaskManager and TaskWorker on app.state instead of module globals,
  removing the lazy-init race and the test reset fixture
- guard all TaskManager state with an RLock now that worker threads
  mutate tasks while request handlers read them
- drop the semaphore from TaskService; concurrency is bounded by the pool
- declare sync endpoints/dependencies as def so blocking work leaves the
  event loop, and keep no-I/O providers async so they stay on it
- count only active tasks against the queue limit and map TaskManager's
  own capacity ValueError to 429
- warn on --workers > 1, which breaks in-process task state
A bare 4-6 digit code like "2330" reaches Yahoo Finance as-is and fails
deep inside the graph ("possibly delisted; no price data found") only
after a background worker has already run the job. validate_ticker_shape
now catches that specific shape synchronously on POST, with a message
pointing at the exchange-suffixed form ("2330" -> "2330.TW"), so the
caller finds out immediately instead of discovering it from a failed
task later.

- Wire the validator into AnalyzeRequest.ticker and TaskCreateRequest.ticker
- Deliberately narrow: only rejects the bare-numeric shape, no network
  validation or rewriting; alphabetic/crypto/already-suffixed tickers
  pass through untouched
- Add MarketDataService.get_price_history() method
  - Validates start_date <= end_date, enforces 1825-day max (stockstats indicator window limit)
  - Retrieves OHLCV bars and technical indicators in aligned window
  - Merges results with per-indicator error tracking
- Add CHART_INDICATORS set: close_50_sma, close_200_sma, boll, boll_ub, boll_lb, rsi, macd, macds, macdh
- Add PriceHistoryResponse schema with nested OHLCVBar, IndicatorSeries, IndicatorPoint
- Add GET /data/history/{ticker} router endpoint
  - Query params: start_date (required), end_date (required), indicators (optional, comma-separated)
  - Nil indicators param → default chart set; empty string → bars only
  - Returns 400 for invalid dates or window > 1825 days
  - Full docstring with window alignment and sentinel value handling
- Add TestPriceHistoryEndpoint with 13 test cases covering:
  - Both tools alignment, default/named/empty indicators
  - Reversed range validation, max history validation, malformed dates
  - Unsupported indicator names, non-trading days with notes
  - Unknown symbols (404), unparsable reports (503)
  - Vendor sentinels, bare crypto resolution

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Add ConfigOverrides schema for type-safe per-request config
- Implement resolve_overrides service to handle research_depth presets
- Add /api/config endpoint to list available configuration options
- Update DecisionService with improved markdown parsing for ratings
- Enhance request/response schemas with override fields
- Add comprehensive test suite for config overrides and decision logic
- Support research_depth presets (shallow/medium/deep) with explicit override precedence

Covers config override resolution, preset expansion, and validation for both
AnalyzeRequest and TaskCreateRequest with support for explicit round counts,
LLM model overrides, and other passthrough fields.
@Kevin0811 Kevin0811 closed this Sep 12, 2026
@Kevin0811
Kevin0811 deleted the feat/api-config-overrides branch September 13, 2026 06:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant