meshagent-anthropic 0.24.6__tar.gz → 0.25.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. {meshagent_anthropic-0.24.6 → meshagent_anthropic-0.25.1}/CHANGELOG.md +16 -2
  2. {meshagent_anthropic-0.24.6/meshagent_anthropic.egg-info → meshagent_anthropic-0.25.1}/PKG-INFO +4 -4
  3. {meshagent_anthropic-0.24.6 → meshagent_anthropic-0.25.1}/meshagent/anthropic/__init__.py +8 -0
  4. {meshagent_anthropic-0.24.6 → meshagent_anthropic-0.25.1}/meshagent/anthropic/mcp.py +6 -8
  5. {meshagent_anthropic-0.24.6 → meshagent_anthropic-0.25.1}/meshagent/anthropic/messages_adapter.py +21 -5
  6. {meshagent_anthropic-0.24.6 → meshagent_anthropic-0.25.1}/meshagent/anthropic/openai_responses_stream_adapter.py +10 -2
  7. meshagent_anthropic-0.25.1/meshagent/anthropic/request_tool.py +28 -0
  8. {meshagent_anthropic-0.24.6 → meshagent_anthropic-0.25.1}/meshagent/anthropic/tests/mcp_test.py +9 -6
  9. meshagent_anthropic-0.25.1/meshagent/anthropic/version.py +1 -0
  10. meshagent_anthropic-0.25.1/meshagent/anthropic/web_fetch.py +73 -0
  11. meshagent_anthropic-0.25.1/meshagent/anthropic/web_search.py +73 -0
  12. {meshagent_anthropic-0.24.6 → meshagent_anthropic-0.25.1/meshagent_anthropic.egg-info}/PKG-INFO +4 -4
  13. {meshagent_anthropic-0.24.6 → meshagent_anthropic-0.25.1}/meshagent_anthropic.egg-info/SOURCES.txt +3 -0
  14. meshagent_anthropic-0.25.1/meshagent_anthropic.egg-info/requires.txt +6 -0
  15. {meshagent_anthropic-0.24.6 → meshagent_anthropic-0.25.1}/pyproject.toml +3 -3
  16. meshagent_anthropic-0.24.6/meshagent/anthropic/version.py +0 -1
  17. meshagent_anthropic-0.24.6/meshagent_anthropic.egg-info/requires.txt +0 -6
  18. {meshagent_anthropic-0.24.6 → meshagent_anthropic-0.25.1}/LICENSE +0 -0
  19. {meshagent_anthropic-0.24.6 → meshagent_anthropic-0.25.1}/MANIFEST.in +0 -0
  20. {meshagent_anthropic-0.24.6 → meshagent_anthropic-0.25.1}/README.md +0 -0
  21. {meshagent_anthropic-0.24.6 → meshagent_anthropic-0.25.1}/meshagent/anthropic/proxy/__init__.py +0 -0
  22. {meshagent_anthropic-0.24.6 → meshagent_anthropic-0.25.1}/meshagent/anthropic/proxy/proxy.py +0 -0
  23. {meshagent_anthropic-0.24.6 → meshagent_anthropic-0.25.1}/meshagent/anthropic/tests/anthropic_live_test.py +0 -0
  24. {meshagent_anthropic-0.24.6 → meshagent_anthropic-0.25.1}/meshagent/anthropic/tests/messages_adapter_test.py +0 -0
  25. {meshagent_anthropic-0.24.6 → meshagent_anthropic-0.25.1}/meshagent/anthropic/tests/openai_responses_stream_adapter_test.py +0 -0
  26. {meshagent_anthropic-0.24.6 → meshagent_anthropic-0.25.1}/meshagent_anthropic.egg-info/dependency_links.txt +0 -0
  27. {meshagent_anthropic-0.24.6 → meshagent_anthropic-0.25.1}/meshagent_anthropic.egg-info/top_level.txt +0 -0
  28. {meshagent_anthropic-0.24.6 → meshagent_anthropic-0.25.1}/setup.cfg +0 -0
@@ -1,5 +1,19 @@
1
- ## [0.24.6]
2
- - Stability
1
+ ## [0.25.1]
2
+ - Added Anthropic web search and web fetch toolkits, including beta header injection and request middleware support.
3
+ - Added a container-based shell tool to run commands in persistent containers with configurable image, mounts, and environment.
4
+ - Expanded the web fetch tool to return text, JSON, or file responses with HTML-to-Markdown conversion and content-type handling.
5
+ - Breaking: CLI commands now reject OpenAI-only tool flags when using Claude models (image generation, local shell, apply patch, computer use).
6
+ - CLI MCP bridge adds streamable HTTP connections plus custom headers and secret-backed headers; OAuth2 secret set now accepts text/base64 input and identity-scoped secrets.
7
+ - Dependency updates: mcp to ~1.26.0; html-to-markdown to ~2.24.3.
8
+
9
+ ## [0.25.0]
10
+ - Added SQL column-schema parsing and CLI support for SQL-like `--columns` when creating tables or adding columns.
11
+ - Breaking: SQL query requests now use a single `params` map for typed bindings instead of `parameters`/`param_values`.
12
+ - Added `published`/`public` port fields in service specs for externally routed services.
13
+ - Secrets set now supports `for_identity` to set secrets on behalf of another identity.
14
+ - Added a Slack events HTTP bot package with dependencies including `pyjwt` 2.10.
15
+ - Breaking: the CLI `exec` command was removed.
16
+ - ThreadAdapter message writing now uses `write_text_message` and accepts participant name strings.
3
17
 
4
18
  ## [0.24.5]
5
19
  - Stability
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshagent-anthropic
3
- Version: 0.24.6
3
+ Version: 0.25.1
4
4
  Summary: Anthropic Building Blocks for Meshagent
5
5
  License-Expression: Apache-2.0
6
6
  Project-URL: Documentation, https://docs.meshagent.com
@@ -11,9 +11,9 @@ Description-Content-Type: text/markdown
11
11
  License-File: LICENSE
12
12
  Requires-Dist: pytest~=8.4
13
13
  Requires-Dist: pytest-asyncio~=0.26
14
- Requires-Dist: meshagent-api~=0.24.6
15
- Requires-Dist: meshagent-agents~=0.24.6
16
- Requires-Dist: meshagent-tools~=0.24.6
14
+ Requires-Dist: meshagent-api~=0.25.1
15
+ Requires-Dist: meshagent-agents~=0.25.1
16
+ Requires-Dist: meshagent-tools~=0.25.1
17
17
  Requires-Dist: anthropic<1.0,>=0.25
18
18
  Dynamic: license-file
19
19
 
@@ -11,6 +11,8 @@ from .mcp import (
11
11
  MCPToolkitBuilder,
12
12
  )
13
13
  from .openai_responses_stream_adapter import AnthropicOpenAIResponsesStreamAdapter
14
+ from .web_fetch import WebFetchConfig, WebFetchTool, WebFetchToolkitBuilder
15
+ from .web_search import WebSearchConfig, WebSearchTool, WebSearchToolkitBuilder
14
16
 
15
17
  __all__ = [
16
18
  AnthropicMessagesAdapter,
@@ -22,4 +24,10 @@ __all__ = [
22
24
  MCPToolConfig,
23
25
  MCPToolset,
24
26
  MCPToolkitBuilder,
27
+ WebFetchConfig,
28
+ WebFetchTool,
29
+ WebFetchToolkitBuilder,
30
+ WebSearchConfig,
31
+ WebSearchTool,
32
+ WebSearchToolkitBuilder,
25
33
  ]
@@ -4,7 +4,9 @@ from typing import Literal, Optional
4
4
 
5
5
  from pydantic import BaseModel
6
6
 
7
- from meshagent.tools import BaseTool, Toolkit, ToolkitBuilder, ToolkitConfig
7
+ from meshagent.tools import Toolkit, ToolkitBuilder, ToolkitConfig
8
+
9
+ from .request_tool import AnthropicRequestTool
8
10
 
9
11
 
10
12
  # This module wraps Anthropic's official MCP connector support:
@@ -56,21 +58,17 @@ class MCPConfig(ToolkitConfig):
56
58
  betas: list[str] = [MCP_CONNECTOR_BETA]
57
59
 
58
60
 
59
- class MCPTool(BaseTool):
61
+ class MCPTool(AnthropicRequestTool):
60
62
  """Non-executable tool that augments the Anthropic request."""
61
63
 
62
64
  def __init__(self, *, config: MCPConfig):
63
65
  super().__init__(name="mcp")
64
66
  self.config = config
65
67
 
66
- def apply(self, *, request: dict) -> None:
68
+ def apply(self, *, request: dict, headers: dict) -> None:
67
69
  """Mutate an Anthropic Messages request in-place."""
68
70
 
69
- # Ensure we use the beta Messages API surface.
70
- betas = request.setdefault("betas", [])
71
- for b in self.config.betas:
72
- if b not in betas:
73
- betas.append(b)
71
+ self.apply_betas(headers=headers, betas=self.config.betas)
74
72
 
75
73
  toolsets = self.config.toolsets
76
74
  if toolsets is None:
@@ -46,7 +46,11 @@ def safe_tool_name(name: str) -> str:
46
46
  def _as_jsonable(obj: Any) -> Any:
47
47
  if isinstance(obj, dict):
48
48
  return obj
49
- return obj.model_dump(mode="json")
49
+ return obj.model_dump(
50
+ mode="json",
51
+ exclude_none=True,
52
+ exclude_unset=True,
53
+ )
50
54
 
51
55
 
52
56
  def _text_block(text: str) -> dict:
@@ -327,6 +331,9 @@ class AnthropicMessagesAdapter(LLMAdapter[dict]):
327
331
  # The MCP connector requires `client.beta.messages.*`.
328
332
  if request.get("betas") is not None:
329
333
  return client.beta.messages
334
+ extra_headers = request.get("extra_headers")
335
+ if isinstance(extra_headers, dict) and extra_headers.get("anthropic-beta"):
336
+ return client.beta.messages
330
337
  return client.messages
331
338
 
332
339
  async def _create_with_optional_headers(self, *, client: Any, request: dict) -> Any:
@@ -372,11 +379,11 @@ class AnthropicMessagesAdapter(LLMAdapter[dict]):
372
379
 
373
380
  def _split_toolkits(
374
381
  self, *, toolkits: list[Toolkit]
375
- ) -> tuple[list[Toolkit], list[MCPConnectorTool]]:
382
+ ) -> tuple[list[Toolkit], list[BaseTool]]:
376
383
  """Split toolkits into executable tools and request middleware tools."""
377
384
 
378
385
  executable_toolkits: list[Toolkit] = []
379
- middleware: list[MCPConnectorTool] = []
386
+ middleware: list[BaseTool] = []
380
387
 
381
388
  for toolkit in toolkits:
382
389
  executable_tools: list[Tool] = []
@@ -387,6 +394,8 @@ class AnthropicMessagesAdapter(LLMAdapter[dict]):
387
394
  elif isinstance(t, Tool):
388
395
  executable_tools.append(t)
389
396
  elif isinstance(t, BaseTool):
397
+ if hasattr(t, "apply") and callable(getattr(t, "apply")):
398
+ middleware.append(t)
390
399
  # Non-executable tool types are ignored.
391
400
  continue
392
401
  else:
@@ -407,10 +416,17 @@ class AnthropicMessagesAdapter(LLMAdapter[dict]):
407
416
  return executable_toolkits, middleware
408
417
 
409
418
  def _apply_request_middleware(
410
- self, *, request: dict, middleware: list[MCPConnectorTool]
419
+ self, *, request: dict, middleware: list[BaseTool]
411
420
  ) -> dict:
421
+ headers = request.get("extra_headers") or {}
412
422
  for m in middleware:
413
- m.apply(request=request)
423
+ apply = getattr(m, "apply", None)
424
+ if callable(apply):
425
+ try:
426
+ apply(request=request, headers=headers)
427
+ except TypeError:
428
+ apply(request=request)
429
+ request["extra_headers"] = headers or None
414
430
  return request
415
431
 
416
432
  async def next(
@@ -114,7 +114,11 @@ class AnthropicOpenAIResponsesStreamAdapter(AnthropicMessagesAdapter):
114
114
 
115
115
  async with client.messages.stream(**request) as stream:
116
116
  async for event in stream:
117
- data = event.model_dump(mode="json")
117
+ data = event.model_dump(
118
+ mode="json",
119
+ exclude_none=True,
120
+ exclude_unset=True,
121
+ )
118
122
  etype = data.get("type")
119
123
 
120
124
  if etype == "message_start":
@@ -356,7 +360,11 @@ class AnthropicOpenAIResponsesStreamAdapter(AnthropicMessagesAdapter):
356
360
  continue
357
361
 
358
362
  final_message = await stream.get_final_message()
359
- final_dict = final_message.model_dump(mode="json")
363
+ final_dict = final_message.model_dump(
364
+ mode="json",
365
+ exclude_none=True,
366
+ exclude_unset=True,
367
+ )
360
368
  usage = final_dict.get("usage") or {}
361
369
  input_tokens = usage.get("input_tokens")
362
370
  output_tokens = usage.get("output_tokens")
@@ -0,0 +1,28 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Optional
4
+
5
+ from meshagent.tools import BaseTool
6
+
7
+
8
+ class AnthropicRequestTool(BaseTool):
9
+ beta_header = "anthropic-beta"
10
+
11
+ @staticmethod
12
+ def apply_betas(*, headers: dict, betas: Optional[list[str]]) -> None:
13
+ if not betas:
14
+ return
15
+
16
+ existing = headers.get(AnthropicRequestTool.beta_header)
17
+ existing_betas: list[str] = []
18
+
19
+ if isinstance(existing, str):
20
+ existing_betas = [b.strip() for b in existing.split(",") if b.strip()]
21
+ elif isinstance(existing, list):
22
+ existing_betas = [str(b) for b in existing if str(b)]
23
+
24
+ for beta in betas:
25
+ if beta not in existing_betas:
26
+ existing_betas.append(beta)
27
+
28
+ headers[AnthropicRequestTool.beta_header] = ",".join(existing_betas)
@@ -11,9 +11,10 @@ def test_mcp_tool_apply_injects_servers_toolsets_and_beta():
11
11
 
12
12
  tool = MCPTool(config=cfg)
13
13
  request: dict = {"tools": []}
14
- tool.apply(request=request)
14
+ headers: dict = {}
15
+ tool.apply(request=request, headers=headers)
15
16
 
16
- assert request["betas"] == ["mcp-client-2025-11-20"]
17
+ assert headers["anthropic-beta"] == "mcp-client-2025-11-20"
17
18
  assert request["mcp_servers"] == [
18
19
  {
19
20
  "type": "url",
@@ -45,14 +46,16 @@ def test_mcp_tool_apply_dedupes_servers_by_name_and_preserves_existing():
45
46
  "authorization_token": "OLD",
46
47
  }
47
48
  ],
48
- "betas": ["some-other-beta"],
49
49
  }
50
50
 
51
- tool.apply(request=request)
51
+ headers: dict = {"anthropic-beta": "some-other-beta"}
52
+
53
+ tool.apply(request=request, headers=headers)
52
54
 
53
55
  # Keeps existing betas and appends MCP beta.
54
- assert "some-other-beta" in request["betas"]
55
- assert "mcp-client-2025-11-20" in request["betas"]
56
+ betas = {b.strip() for b in headers["anthropic-beta"].split(",") if b.strip()}
57
+ assert "some-other-beta" in betas
58
+ assert "mcp-client-2025-11-20" in betas
56
59
 
57
60
  # Dedupes by name; cfg overwrites the existing server entry.
58
61
  by_name = {s["name"]: s for s in request["mcp_servers"]}
@@ -0,0 +1 @@
1
+ __version__ = "0.25.1"
@@ -0,0 +1,73 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Literal, Optional
4
+
5
+ from pydantic import BaseModel, Field
6
+
7
+ from meshagent.tools import Toolkit, ToolkitBuilder, ToolkitConfig
8
+
9
+ from .request_tool import AnthropicRequestTool
10
+
11
+
12
+ class WebFetchCitations(BaseModel):
13
+ enabled: bool = True
14
+
15
+
16
+ class WebFetchConfig(ToolkitConfig):
17
+ name: Literal["web_fetch"] = "web_fetch"
18
+ max_uses: Optional[int] = None
19
+ allowed_domains: Optional[list[str]] = None
20
+ blocked_domains: Optional[list[str]] = None
21
+ citations: Optional[WebFetchCitations] = None
22
+ max_content_tokens: Optional[int] = None
23
+ betas: Optional[list[str]] = Field(default_factory=lambda: ["web-fetch-2025-09-10"])
24
+
25
+
26
+ class WebFetchTool(AnthropicRequestTool):
27
+ def __init__(self, *, config: Optional[WebFetchConfig] = None):
28
+ if config is None:
29
+ config = WebFetchConfig(name="web_fetch")
30
+ super().__init__(name=config.name)
31
+ self.config = config
32
+
33
+ def apply(self, *, request: dict, headers: dict) -> None:
34
+ if self.config.allowed_domains and self.config.blocked_domains:
35
+ raise ValueError(
36
+ "web_fetch cannot set both allowed_domains and blocked_domains"
37
+ )
38
+
39
+ tools = request.setdefault("tools", [])
40
+ tool_def: dict[str, object] = {
41
+ "type": "web_fetch_20250910",
42
+ "name": self.config.name,
43
+ }
44
+ if self.config.max_uses is not None:
45
+ tool_def["max_uses"] = self.config.max_uses
46
+ if self.config.allowed_domains is not None:
47
+ tool_def["allowed_domains"] = self.config.allowed_domains
48
+ if self.config.blocked_domains is not None:
49
+ tool_def["blocked_domains"] = self.config.blocked_domains
50
+ if self.config.citations is not None:
51
+ tool_def["citations"] = self.config.citations.model_dump(
52
+ mode="json", exclude_none=True
53
+ )
54
+ if self.config.max_content_tokens is not None:
55
+ tool_def["max_content_tokens"] = self.config.max_content_tokens
56
+
57
+ if not any(
58
+ isinstance(t, dict)
59
+ and t.get("type") == tool_def["type"]
60
+ and t.get("name") == tool_def["name"]
61
+ for t in tools
62
+ ):
63
+ tools.append(tool_def)
64
+
65
+ self.apply_betas(headers=headers, betas=self.config.betas)
66
+
67
+
68
+ class WebFetchToolkitBuilder(ToolkitBuilder):
69
+ def __init__(self):
70
+ super().__init__(name="web_fetch", type=WebFetchConfig)
71
+
72
+ async def make(self, *, room, model: str, config: WebFetchConfig) -> Toolkit:
73
+ return Toolkit(name="web_fetch", tools=[WebFetchTool(config=config)])
@@ -0,0 +1,73 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Literal, Optional
4
+
5
+ from pydantic import BaseModel
6
+
7
+ from meshagent.tools import Toolkit, ToolkitBuilder, ToolkitConfig
8
+
9
+ from .request_tool import AnthropicRequestTool
10
+
11
+
12
+ class WebSearchConfig(ToolkitConfig):
13
+ name: Literal["web_search"] = "web_search"
14
+ max_uses: Optional[int] = None
15
+ allowed_domains: Optional[list[str]] = None
16
+ blocked_domains: Optional[list[str]] = None
17
+ user_location: Optional["WebSearchUserLocation"] = None
18
+ betas: Optional[list[str]] = None
19
+
20
+
21
+ class WebSearchUserLocation(BaseModel):
22
+ type: Literal["approximate"] = "approximate"
23
+ city: Optional[str] = None
24
+ region: Optional[str] = None
25
+ country: Optional[str] = None
26
+ timezone: Optional[str] = None
27
+
28
+
29
+ class WebSearchTool(AnthropicRequestTool):
30
+ def __init__(self, *, config: Optional[WebSearchConfig] = None):
31
+ if config is None:
32
+ config = WebSearchConfig(name="web_search")
33
+ super().__init__(name=config.name)
34
+ self.config = config
35
+
36
+ def apply(self, *, request: dict, headers: dict) -> None:
37
+ if self.config.allowed_domains and self.config.blocked_domains:
38
+ raise ValueError(
39
+ "web_search cannot set both allowed_domains and blocked_domains"
40
+ )
41
+
42
+ tools = request.setdefault("tools", [])
43
+ tool_def: dict[str, object] = {
44
+ "type": "web_search_20250305",
45
+ "name": self.config.name,
46
+ }
47
+ if self.config.max_uses is not None:
48
+ tool_def["max_uses"] = self.config.max_uses
49
+ if self.config.allowed_domains is not None:
50
+ tool_def["allowed_domains"] = self.config.allowed_domains
51
+ if self.config.blocked_domains is not None:
52
+ tool_def["blocked_domains"] = self.config.blocked_domains
53
+ if self.config.user_location is not None:
54
+ tool_def["user_location"] = self.config.user_location.model_dump(
55
+ mode="json", exclude_none=True
56
+ )
57
+ if not any(
58
+ isinstance(t, dict)
59
+ and t.get("type") == tool_def["type"]
60
+ and t.get("name") == tool_def["name"]
61
+ for t in tools
62
+ ):
63
+ tools.append(tool_def)
64
+
65
+ self.apply_betas(headers=headers, betas=self.config.betas)
66
+
67
+
68
+ class WebSearchToolkitBuilder(ToolkitBuilder):
69
+ def __init__(self):
70
+ super().__init__(name="web_search", type=WebSearchConfig)
71
+
72
+ async def make(self, *, room, model: str, config: WebSearchConfig) -> Toolkit:
73
+ return Toolkit(name="web_search", tools=[WebSearchTool(config=config)])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshagent-anthropic
3
- Version: 0.24.6
3
+ Version: 0.25.1
4
4
  Summary: Anthropic Building Blocks for Meshagent
5
5
  License-Expression: Apache-2.0
6
6
  Project-URL: Documentation, https://docs.meshagent.com
@@ -11,9 +11,9 @@ Description-Content-Type: text/markdown
11
11
  License-File: LICENSE
12
12
  Requires-Dist: pytest~=8.4
13
13
  Requires-Dist: pytest-asyncio~=0.26
14
- Requires-Dist: meshagent-api~=0.24.6
15
- Requires-Dist: meshagent-agents~=0.24.6
16
- Requires-Dist: meshagent-tools~=0.24.6
14
+ Requires-Dist: meshagent-api~=0.25.1
15
+ Requires-Dist: meshagent-agents~=0.25.1
16
+ Requires-Dist: meshagent-tools~=0.25.1
17
17
  Requires-Dist: anthropic<1.0,>=0.25
18
18
  Dynamic: license-file
19
19
 
@@ -7,7 +7,10 @@ meshagent/anthropic/__init__.py
7
7
  meshagent/anthropic/mcp.py
8
8
  meshagent/anthropic/messages_adapter.py
9
9
  meshagent/anthropic/openai_responses_stream_adapter.py
10
+ meshagent/anthropic/request_tool.py
10
11
  meshagent/anthropic/version.py
12
+ meshagent/anthropic/web_fetch.py
13
+ meshagent/anthropic/web_search.py
11
14
  meshagent/anthropic/proxy/__init__.py
12
15
  meshagent/anthropic/proxy/proxy.py
13
16
  meshagent/anthropic/tests/anthropic_live_test.py
@@ -0,0 +1,6 @@
1
+ pytest~=8.4
2
+ pytest-asyncio~=0.26
3
+ meshagent-api~=0.25.1
4
+ meshagent-agents~=0.25.1
5
+ meshagent-tools~=0.25.1
6
+ anthropic<1.0,>=0.25
@@ -12,9 +12,9 @@ keywords = []
12
12
  dependencies = [
13
13
  "pytest~=8.4",
14
14
  "pytest-asyncio~=0.26",
15
- "meshagent-api~=0.24.6",
16
- "meshagent-agents~=0.24.6",
17
- "meshagent-tools~=0.24.6",
15
+ "meshagent-api~=0.25.1",
16
+ "meshagent-agents~=0.25.1",
17
+ "meshagent-tools~=0.25.1",
18
18
  "anthropic>=0.25,<1.0"
19
19
  ]
20
20
 
@@ -1 +0,0 @@
1
- __version__ = "0.24.6"
@@ -1,6 +0,0 @@
1
- pytest~=8.4
2
- pytest-asyncio~=0.26
3
- meshagent-api~=0.24.6
4
- meshagent-agents~=0.24.6
5
- meshagent-tools~=0.24.6
6
- anthropic<1.0,>=0.25