Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/api/src/cell_explorer_api/services/chat_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,10 @@ async def make_chat_agent(

# 6. Construct LLMClient if not provided
if llm is None:
llm = AnthropicLLMClient(transport=agent_config.llm_transport)
llm = AnthropicLLMClient(
transport=agent_config.llm_transport,
bedrock_region=agent_config.bedrock_region,
)

# 7. Return the wired agent
return ChatAgent(llm=llm, catalog=catalog, dataset_ctx=ctx, config=agent_config)
2 changes: 1 addition & 1 deletion packages/cell-explorer-agent/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.1.0"
description = "LLM chat agent library for single-cell zarr datasets"
requires-python = ">=3.12"
dependencies = [
"anthropic>=0.40",
"anthropic[bedrock]>=0.40",
"pydantic>=2.0",
"pydantic-settings>=2.8",
"numpy>=1.26",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class AgentConfig(BaseSettings):

llm_transport: Literal["anthropic", "bedrock", "vertex"] = "anthropic"
llm_model: str = "claude-sonnet-4-6"
bedrock_region: str = "us-east-1"

tool_result_max_bytes: int = Field(default=32_768, ge=1)
filter_ids_max: int = Field(default=100_000, ge=1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,15 @@ def neutral_messages_to_anthropic(
class AnthropicLLMClient(LLMClient):
"""Anthropic SDK adapter. Supports direct/Bedrock/Vertex via transport arg."""

def __init__(self, *, transport: Transport = "anthropic") -> None:
def __init__(
self, *, transport: Transport = "anthropic", bedrock_region: str = "us-east-1"
) -> None:
import anthropic

if transport == "anthropic":
self._client = anthropic.AsyncAnthropic()
elif transport == "bedrock":
self._client = anthropic.AsyncAnthropicBedrock()
self._client = anthropic.AsyncAnthropicBedrock(aws_region=bedrock_region)
elif transport == "vertex":
self._client = anthropic.AsyncAnthropicVertex()
else:
Expand Down
11 changes: 11 additions & 0 deletions packages/cell-explorer-agent/tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ def test_defaults():
cfg = AgentConfig()
assert cfg.llm_transport == "anthropic"
assert cfg.llm_model == "claude-sonnet-4-6"
assert cfg.bedrock_region == "us-east-1"
assert cfg.tool_result_max_bytes == 32_768
assert cfg.filter_ids_max == 100_000
assert cfg.max_tool_calls_per_turn == 8
Expand Down Expand Up @@ -98,3 +99,13 @@ def test_langfuse_base_url_default(monkeypatch):
from cell_explorer_agent.config import AgentConfig
cfg = AgentConfig()
assert cfg.langfuse_base_url == "https://us.cloud.langfuse.com"


def test_bedrock_region_default(monkeypatch):
monkeypatch.delenv("CHAT_BEDROCK_REGION", raising=False)
assert AgentConfig().bedrock_region == "us-east-1"


def test_bedrock_region_override(monkeypatch):
monkeypatch.setenv("CHAT_BEDROCK_REGION", "us-west-2")
assert AgentConfig().bedrock_region == "us-west-2"
31 changes: 31 additions & 0 deletions packages/cell-explorer-agent/tests/test_llm_client_transport.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""AnthropicLLMClient transport selection + Bedrock runtime deps."""

import anthropic

from cell_explorer_agent import AnthropicLLMClient


def test_bedrock_runtime_dep_importable():
# anthropic[bedrock] provides boto3, required for Bedrock SigV4/cred resolution
# at request time (construction alone does not import it).
import boto3 # noqa: F401


def test_bedrock_transport_uses_region():
# Non-default region so this fails if aws_region were dropped from the
# constructor call (the SDK would otherwise fall back to "us-east-1").
client = AnthropicLLMClient(transport="bedrock", bedrock_region="ap-southeast-1")
assert isinstance(client._client, anthropic.AsyncAnthropicBedrock)
assert client._client.aws_region == "ap-southeast-1"


def test_bedrock_transport_region_override():
client = AnthropicLLMClient(transport="bedrock", bedrock_region="eu-west-1")
assert client._client.aws_region == "eu-west-1"


def test_anthropic_transport_is_default(monkeypatch):
# AsyncAnthropic() needs an api key present to construct
monkeypatch.setenv("ANTHROPIC_API_KEY", "sk-ant-test")
client = AnthropicLLMClient()
assert isinstance(client._client, anthropic.AsyncAnthropic)
59 changes: 57 additions & 2 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading