Captured after the stats-callback fix so the run reflects the
working LLM/Tools/Tokens counters in the CLI TUI.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ChatClaudeAgent is a plain Runnable rather than a BaseChatModel, so
LangChain's callback system never fired on_chat_model_start / on_llm_end
for it — leaving the CLI TUI stuck on "LLM: 0" and "Tokens: --" during
runs. Pop callbacks out of the LLM kwargs, invoke them manually around
each SDK call, and attach usage_metadata extracted from the SDK's
ResultMessage (input, output, total — including cached input) to the
returned AIMessage so downstream handlers pick it up.
Tool callbacks now also fire through the MCP wrapper: forward the
callback list into each wrapped LangChain tool's invocation config so
StatsCallbackHandler sees on_tool_start/on_tool_end when the SDK loop
calls a tool.
Verified via direct StatsCallbackHandler round-trip on both Shape A
(ChatClaudeAgent.invoke) and Shape B (run_sdk_analyst): llm_calls,
tool_calls, tokens_in, and tokens_out all increment as expected.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move Claude Agent to the top of the provider list so it's the default
highlight. Drop the redundant "(via Claude Code, Max subscription)"
suffix on each model entry — the provider step already makes the auth
path clear — and expose all three tiers (Opus / Sonnet / Haiku) in
both the quick and deep lists, ordered by the sensible pick for each.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Full pipeline output from a Max-subscription run (SPY, 2026-04-14) with
all 4 analysts, researcher debate, trader plan, risk debate, and portfolio
manager decision. Captured as evidence that the branch produces coherent
reports end-to-end without any API key.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CLI: add "Claude Agent (Max subscription, no API key)" to the provider
picker and register opus/sonnet/haiku model aliases so the CLI flow picks
up the provider registered in factory.py. No effort-level step since the
SDK doesn't expose that knob.
Analyst runner: build a concrete user request from company_of_interest +
trade_date instead of echoing the terse ("human", ticker) initial state —
the SDK was sitting idle on prompts like just "NVDA". Add opt-in file-
based debug logging (TRADINGAGENTS_CLAUDE_AGENT_DEBUG=1 → /tmp/...log)
for observability during long adaptive-thinking blocks.
Also adds main_claude_agent.py as a ready-to-run example for a Max-only
end-to-end invocation (verified 12-min NVDA run → SELL).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The 4 analysts (market, news, social, fundamentals) now detect a
ChatClaudeAgent LLM and dispatch to an SDK-native runner: LangChain @tool
functions are wrapped as in-process MCP tools via create_sdk_mcp_server, and
the SDK owns the iterative tool-calling loop. Claude returns the final report
in one call, so the analyst node outputs an AIMessage with no tool_calls and
the existing conditional edges route straight to the message-clear step.
Together with the Shape A provider this lets a Claude Max subscription drive
the full TradingAgents graph without an Anthropic API key. Other providers
continue to take the original bind_tools + LangGraph ToolNode path unchanged.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds claude-agent-sdk>=0.1.59 to pyproject.toml. Running uv lock also
reconciled ~1600 lines of orphaned entries (opentelemetry, posthog,
traceloop-sdk, uptrace, etc.) that had been removed from pyproject.toml
in earlier changes without re-locking.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Routes inference through Claude Code's OAuth session, so a Claude Max/Pro
subscription authenticates without an Anthropic API key. Shape A supports
plain .invoke() for prompt-only call sites (researchers, managers, trader,
reflection, signal processing); bind_tools raises NotImplementedError until
Shape B rewrites analysts to use the SDK's native tool loop.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Apply review suggestions: use concise `or` pattern for API key
resolution, consolidate tests into parameterized subTest, move
import to module level per PEP 8.
GoogleClient now accepts the unified `api_key` parameter used by
OpenAI and Anthropic clients, mapping it to the provider-specific
`google_api_key` that ChatGoogleGenerativeAI expects. Legacy
`google_api_key` still works for backward compatibility.
Resolves TODO.md item #2 (inconsistent parameter handling).
Add effort parameter (high/medium/low) for Claude 4.5+ and 4.6 models,
consistent with OpenAI reasoning_effort and Google thinking_level.
Also add content normalization for Anthropic responses.
- Point requirements.txt to pyproject.toml as single source of truth
- Resolve welcome.txt path relative to module for CLI portability
- Include cli/static files in package build
- Extract shared normalize_content for OpenAI Responses API and
Gemini 3 list-format responses into base_client.py
- Update README install and CLI usage instructions
Enable use_responses_api for native OpenAI provider, which supports
reasoning_effort with function tools across all model families.
Removes the UnifiedChatOpenAI subclass workaround.
Closes#403
- Add http_client and http_async_client parameters to all LLM clients
- OpenAIClient, GoogleClient, AnthropicClient now support custom httpx clients
- Fixes SSL certificate verification errors on Windows Conda environments
- Users can now pass custom httpx.Client with verify=False or custom certs
Fixes#369
- OpenAI: add GPT-5.4, GPT-5.4 Pro; remove o-series and legacy GPT-4o
- Anthropic: add Claude Opus 4.6, Sonnet 4.6; remove legacy 4.1/4.0/3.x
- Google: add Gemini 3.1 Pro, 3.1 Flash Lite; remove deprecated
gemini-3-pro-preview and Gemini 2.0 series
- xAI: clean up model list to match current API
- Simplify UnifiedChatOpenAI GPT-5 temperature handling
- Add missing tradingagents/__init__.py (fixes pip install building)
Add _clean_dataframe() to normalize stock DataFrames before stockstats:
coerce invalid dates/prices, drop rows missing Close, fill price gaps.
Also add on_bad_lines="skip" to all cached CSV reads.