agentx-kit 0.2.0__py3-none-any.whl
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.
- agentx/__init__.py +55 -0
- agentx/cli.py +230 -0
- agentx/config.py +34 -0
- agentx/frameworks/__init__.py +5 -0
- agentx/frameworks/crewai_agent.py +52 -0
- agentx/frameworks/langchain_agent.py +43 -0
- agentx/guardrails.py +89 -0
- agentx/memory/__init__.py +4 -0
- agentx/memory/store.py +78 -0
- agentx/observability.py +103 -0
- agentx/prompts/__init__.py +8 -0
- agentx/prompts/templates.py +40 -0
- agentx/providers/__init__.py +15 -0
- agentx/providers/base.py +50 -0
- agentx/providers/factory.py +71 -0
- agentx/providers/registry.py +165 -0
- agentx/rag/__init__.py +8 -0
- agentx/rag/pipeline.py +121 -0
- agentx/reliability.py +112 -0
- agentx/scaffold/__init__.py +14 -0
- agentx/scaffold/generator.py +190 -0
- agentx/scaffold/prompts_store.py +99 -0
- agentx/scaffold/spec.py +85 -0
- agentx/scaffold/templates/Dockerfile.j2 +17 -0
- agentx/scaffold/templates/README.md.j2 +46 -0
- agentx/scaffold/templates/ci.yml.j2 +41 -0
- agentx/scaffold/templates/docker-compose.yml.j2 +9 -0
- agentx/scaffold/templates/dockerignore.j2 +11 -0
- agentx/scaffold/templates/env.example.j2 +12 -0
- agentx/scaffold/templates/evals/dataset.json.j2 +10 -0
- agentx/scaffold/templates/evals/run_evals.py.j2 +70 -0
- agentx/scaffold/templates/gitignore.j2 +8 -0
- agentx/scaffold/templates/mcp_servers.json.j2 +7 -0
- agentx/scaffold/templates/pkg/__init__.py.j2 +3 -0
- agentx/scaffold/templates/pkg/agents.py.j2 +77 -0
- agentx/scaffold/templates/pkg/config.py.j2 +25 -0
- agentx/scaffold/templates/pkg/guardrails.py.j2 +21 -0
- agentx/scaffold/templates/pkg/main.py.j2 +79 -0
- agentx/scaffold/templates/pkg/memory.py.j2 +17 -0
- agentx/scaffold/templates/pkg/observability.py.j2 +17 -0
- agentx/scaffold/templates/pkg/prompts.py.j2 +45 -0
- agentx/scaffold/templates/pkg/rag.py.j2 +37 -0
- agentx/scaffold/templates/pkg/server.py.j2 +85 -0
- agentx/scaffold/templates/pkg/tools.py.j2 +16 -0
- agentx/scaffold/templates/pyproject.toml.j2 +28 -0
- agentx/scaffold/templates/skills_seed.json.j2 +6 -0
- agentx/scaffold/wizard.py +125 -0
- agentx/skills/__init__.py +4 -0
- agentx/skills/registry.py +63 -0
- agentx/structured.py +37 -0
- agentx/tools/__init__.py +5 -0
- agentx/tools/builtin.py +45 -0
- agentx/tools/mcp.py +64 -0
- agentx_kit-0.2.0.dist-info/METADATA +289 -0
- agentx_kit-0.2.0.dist-info/RECORD +58 -0
- agentx_kit-0.2.0.dist-info/WHEEL +4 -0
- agentx_kit-0.2.0.dist-info/entry_points.txt +2 -0
- agentx_kit-0.2.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""Filesystem-backed skill registry.
|
|
2
|
+
|
|
3
|
+
A *skill* is a named instruction block (e.g. "Always use the STAR method") that
|
|
4
|
+
gets injected into agent prompts. Skills are stored as JSON files under a
|
|
5
|
+
directory so users can add/version them outside the code.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
import re
|
|
11
|
+
from dataclasses import asdict, dataclass
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _slug(name: str) -> str:
|
|
16
|
+
return re.sub(r"[^a-z0-9]+", "-", name.strip().lower()).strip("-") or "skill"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
class Skill:
|
|
21
|
+
slug: str
|
|
22
|
+
name: str
|
|
23
|
+
description: str
|
|
24
|
+
instructions: str
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class SkillRegistry:
|
|
28
|
+
def __init__(self, directory: str | Path):
|
|
29
|
+
self.dir = Path(directory)
|
|
30
|
+
self.dir.mkdir(parents=True, exist_ok=True)
|
|
31
|
+
|
|
32
|
+
def add(self, name: str, description: str, instructions: str) -> Skill:
|
|
33
|
+
if not name.strip():
|
|
34
|
+
raise ValueError("Skill name is required.")
|
|
35
|
+
skill = Skill(_slug(name), name.strip(), description.strip(), instructions.strip())
|
|
36
|
+
(self.dir / f"{skill.slug}.json").write_text(json.dumps(asdict(skill), indent=2), encoding="utf-8")
|
|
37
|
+
return skill
|
|
38
|
+
|
|
39
|
+
def list(self) -> list[Skill]:
|
|
40
|
+
out: list[Skill] = []
|
|
41
|
+
for fp in sorted(self.dir.glob("*.json")):
|
|
42
|
+
try:
|
|
43
|
+
out.append(Skill(**json.loads(fp.read_text(encoding="utf-8"))))
|
|
44
|
+
except Exception: # noqa: BLE001 - skip malformed files
|
|
45
|
+
continue
|
|
46
|
+
return out
|
|
47
|
+
|
|
48
|
+
def delete(self, slug: str) -> None:
|
|
49
|
+
(self.dir / f"{slug}.json").unlink(missing_ok=True)
|
|
50
|
+
|
|
51
|
+
def combined_instructions(self, slugs: list[str] | None = None) -> str:
|
|
52
|
+
"""Concatenate selected (or all) skills' instructions for prompt injection."""
|
|
53
|
+
skills = self.list()
|
|
54
|
+
if slugs:
|
|
55
|
+
wanted = set(slugs)
|
|
56
|
+
skills = [s for s in skills if s.slug in wanted]
|
|
57
|
+
if not skills:
|
|
58
|
+
return ""
|
|
59
|
+
return "\n".join(f"- {s.name}: {s.instructions}" for s in skills)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def get_skill_registry(directory: str | Path = "data/skills") -> SkillRegistry:
|
|
63
|
+
return SkillRegistry(directory)
|
agentx/structured.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""Structured outputs — typed, validated model responses.
|
|
2
|
+
|
|
3
|
+
Thin, provider-agnostic wrappers over LangChain's ``with_structured_output``
|
|
4
|
+
(supported across OpenAI, Anthropic, Gemini, Bedrock, Groq, Ollama, …). Pass a
|
|
5
|
+
Pydantic model or a JSON schema; get back validated objects instead of strings.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from .providers import get_chat_model
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def structured_model(schema: Any, provider: str | None = None, model: str | None = None, **kwargs):
|
|
15
|
+
"""Return a chat model that emits instances of ``schema`` (a Pydantic model).
|
|
16
|
+
|
|
17
|
+
Example::
|
|
18
|
+
|
|
19
|
+
from pydantic import BaseModel
|
|
20
|
+
class Person(BaseModel):
|
|
21
|
+
name: str
|
|
22
|
+
age: int
|
|
23
|
+
llm = structured_model(Person, "openai", "gpt-4o-mini")
|
|
24
|
+
person = llm.invoke("Alice is 30") # -> Person(name='Alice', age=30)
|
|
25
|
+
"""
|
|
26
|
+
llm = get_chat_model(provider, model, **kwargs)
|
|
27
|
+
return as_structured(llm, schema)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def as_structured(llm: Any, schema: Any):
|
|
31
|
+
"""Attach structured-output decoding to an existing chat model."""
|
|
32
|
+
if not hasattr(llm, "with_structured_output"):
|
|
33
|
+
raise TypeError(
|
|
34
|
+
f"{type(llm).__name__} does not support structured output; "
|
|
35
|
+
"use a provider/model that implements with_structured_output()."
|
|
36
|
+
)
|
|
37
|
+
return llm.with_structured_output(schema)
|
agentx/tools/__init__.py
ADDED
agentx/tools/builtin.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Built-in tools usable by agents. Currently: a keyless web search.
|
|
2
|
+
|
|
3
|
+
Uses the ``ddgs`` (DuckDuckGo) package if available; otherwise the tool returns
|
|
4
|
+
a friendly message instead of failing.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def web_search(query: str, max_results: int = 5) -> str:
|
|
14
|
+
"""Run a DuckDuckGo text search and return a formatted string."""
|
|
15
|
+
try:
|
|
16
|
+
from ddgs import DDGS
|
|
17
|
+
except ImportError:
|
|
18
|
+
try:
|
|
19
|
+
from duckduckgo_search import DDGS # older package name
|
|
20
|
+
except ImportError:
|
|
21
|
+
return "Web search unavailable (install `ddgs`)."
|
|
22
|
+
try:
|
|
23
|
+
lines = []
|
|
24
|
+
with DDGS() as ddgs:
|
|
25
|
+
for r in ddgs.text(query, max_results=max_results):
|
|
26
|
+
title = r.get("title", "")
|
|
27
|
+
body = r.get("body", "")
|
|
28
|
+
url = r.get("href", r.get("url", ""))
|
|
29
|
+
lines.append(f"- {title}\n {body}\n {url}")
|
|
30
|
+
return "\n".join(lines) if lines else f"No results for '{query}'."
|
|
31
|
+
except Exception as exc: # noqa: BLE001
|
|
32
|
+
logger.warning("web_search failed: %s", exc)
|
|
33
|
+
return f"Web search error: {exc!r}"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def make_web_search_tool():
|
|
37
|
+
"""Return ``web_search`` wrapped as a LangChain ``@tool`` (lazy import)."""
|
|
38
|
+
from langchain_core.tools import tool
|
|
39
|
+
|
|
40
|
+
@tool
|
|
41
|
+
def web_search_tool(query: str) -> str:
|
|
42
|
+
"""Search the public web for up-to-date information. Input a concise query."""
|
|
43
|
+
return web_search(query)
|
|
44
|
+
|
|
45
|
+
return web_search_tool
|
agentx/tools/mcp.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""Load MCP servers as LangChain tools via ``langchain-mcp-adapters``.
|
|
2
|
+
|
|
3
|
+
Config format (JSON or dict) follows MultiServerMCPClient, e.g.::
|
|
4
|
+
|
|
5
|
+
{
|
|
6
|
+
"filesystem": {
|
|
7
|
+
"command": "npx",
|
|
8
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path"],
|
|
9
|
+
"transport": "stdio"
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
Returns ``[]`` (never raises) if the extra isn't installed or loading fails, so
|
|
14
|
+
agents degrade gracefully.
|
|
15
|
+
"""
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import asyncio
|
|
19
|
+
import json
|
|
20
|
+
import logging
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
from typing import Any
|
|
23
|
+
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _load_config(config: str | Path | dict | None) -> dict:
|
|
28
|
+
if config is None:
|
|
29
|
+
return {}
|
|
30
|
+
if isinstance(config, dict):
|
|
31
|
+
return config
|
|
32
|
+
p = Path(config)
|
|
33
|
+
if p.exists():
|
|
34
|
+
return json.loads(p.read_text(encoding="utf-8"))
|
|
35
|
+
return {}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def load_mcp_tools(config: str | Path | dict | None) -> list[Any]:
|
|
39
|
+
"""Synchronously load MCP tools from a config path/dict. Returns [] on failure."""
|
|
40
|
+
servers = _load_config(config)
|
|
41
|
+
if not servers:
|
|
42
|
+
return []
|
|
43
|
+
try:
|
|
44
|
+
from langchain_mcp_adapters.client import MultiServerMCPClient
|
|
45
|
+
except ImportError:
|
|
46
|
+
logger.warning("langchain-mcp-adapters not installed; run `uv pip install 'agentx-kit[mcp]'`.")
|
|
47
|
+
return []
|
|
48
|
+
|
|
49
|
+
async def _gather() -> list[Any]:
|
|
50
|
+
client = MultiServerMCPClient(servers)
|
|
51
|
+
return await client.get_tools()
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
return asyncio.run(_gather())
|
|
55
|
+
except RuntimeError:
|
|
56
|
+
# Already inside an event loop (e.g. notebook) — run in a fresh loop.
|
|
57
|
+
loop = asyncio.new_event_loop()
|
|
58
|
+
try:
|
|
59
|
+
return loop.run_until_complete(_gather())
|
|
60
|
+
finally:
|
|
61
|
+
loop.close()
|
|
62
|
+
except Exception as exc: # noqa: BLE001
|
|
63
|
+
logger.warning("Failed to load MCP tools: %s", exc)
|
|
64
|
+
return []
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentx-kit
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: An open-source, provider-agnostic agentic framework + interactive project scaffolder for LangChain and CrewAI. Pick your LLM provider, agents, RAG, memory, MCP tools and skills — generate a ready-to-run uv project.
|
|
5
|
+
Project-URL: Homepage, https://github.com/muhammadyahiya/agentx-kit
|
|
6
|
+
Project-URL: Repository, https://github.com/muhammadyahiya/agentx-kit
|
|
7
|
+
Project-URL: Issues, https://github.com/muhammadyahiya/agentx-kit/issues
|
|
8
|
+
Author: AgentX
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agents,azure,bedrock,crewai,gemini,langchain,llm,mcp,openrouter,rag,scaffold,vertex
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
22
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
23
|
+
Requires-Python: <3.14,>=3.10
|
|
24
|
+
Requires-Dist: jinja2>=3.1.0
|
|
25
|
+
Requires-Dist: langchain-core>=0.3.0
|
|
26
|
+
Requires-Dist: pydantic-settings>=2.2.0
|
|
27
|
+
Requires-Dist: pydantic>=2.7.0
|
|
28
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
29
|
+
Requires-Dist: questionary>=2.0.0
|
|
30
|
+
Requires-Dist: rich>=13.7.0
|
|
31
|
+
Requires-Dist: typer>=0.12.0
|
|
32
|
+
Provides-Extra: all
|
|
33
|
+
Requires-Dist: chromadb>=0.5.0; extra == 'all'
|
|
34
|
+
Requires-Dist: fastapi>=0.110.0; extra == 'all'
|
|
35
|
+
Requires-Dist: langchain-anthropic>=0.2.0; extra == 'all'
|
|
36
|
+
Requires-Dist: langchain-aws>=0.2.0; extra == 'all'
|
|
37
|
+
Requires-Dist: langchain-community>=0.3.0; extra == 'all'
|
|
38
|
+
Requires-Dist: langchain-google-genai>=2.0.0; extra == 'all'
|
|
39
|
+
Requires-Dist: langchain-google-vertexai>=2.0.0; extra == 'all'
|
|
40
|
+
Requires-Dist: langchain-groq>=0.2.0; extra == 'all'
|
|
41
|
+
Requires-Dist: langchain-mcp-adapters>=0.1.0; extra == 'all'
|
|
42
|
+
Requires-Dist: langchain-ollama>=0.2.0; extra == 'all'
|
|
43
|
+
Requires-Dist: langchain-openai>=0.2.0; extra == 'all'
|
|
44
|
+
Requires-Dist: langchain-text-splitters>=0.3.0; extra == 'all'
|
|
45
|
+
Requires-Dist: langchain>=0.3.0; extra == 'all'
|
|
46
|
+
Requires-Dist: langgraph>=0.2.0; extra == 'all'
|
|
47
|
+
Requires-Dist: mcp>=1.2.0; extra == 'all'
|
|
48
|
+
Requires-Dist: openinference-instrumentation-langchain>=0.1.0; extra == 'all'
|
|
49
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.20.0; extra == 'all'
|
|
50
|
+
Requires-Dist: opentelemetry-sdk>=1.20.0; extra == 'all'
|
|
51
|
+
Requires-Dist: sse-starlette>=2.0.0; extra == 'all'
|
|
52
|
+
Requires-Dist: uvicorn[standard]>=0.29.0; extra == 'all'
|
|
53
|
+
Provides-Extra: anthropic
|
|
54
|
+
Requires-Dist: langchain-anthropic>=0.2.0; extra == 'anthropic'
|
|
55
|
+
Provides-Extra: azure
|
|
56
|
+
Requires-Dist: langchain-openai>=0.2.0; extra == 'azure'
|
|
57
|
+
Provides-Extra: bedrock
|
|
58
|
+
Requires-Dist: langchain-aws>=0.2.0; extra == 'bedrock'
|
|
59
|
+
Provides-Extra: crewai
|
|
60
|
+
Requires-Dist: crewai>=0.70.0; extra == 'crewai'
|
|
61
|
+
Provides-Extra: dev
|
|
62
|
+
Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
|
|
63
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
64
|
+
Provides-Extra: google
|
|
65
|
+
Requires-Dist: langchain-google-genai>=2.0.0; extra == 'google'
|
|
66
|
+
Provides-Extra: groq
|
|
67
|
+
Requires-Dist: langchain-groq>=0.2.0; extra == 'groq'
|
|
68
|
+
Provides-Extra: langgraph
|
|
69
|
+
Requires-Dist: langchain>=0.3.0; extra == 'langgraph'
|
|
70
|
+
Requires-Dist: langgraph>=0.2.0; extra == 'langgraph'
|
|
71
|
+
Provides-Extra: mcp
|
|
72
|
+
Requires-Dist: langchain-mcp-adapters>=0.1.0; extra == 'mcp'
|
|
73
|
+
Requires-Dist: mcp>=1.2.0; extra == 'mcp'
|
|
74
|
+
Provides-Extra: observability
|
|
75
|
+
Requires-Dist: openinference-instrumentation-langchain>=0.1.0; extra == 'observability'
|
|
76
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.20.0; extra == 'observability'
|
|
77
|
+
Requires-Dist: opentelemetry-sdk>=1.20.0; extra == 'observability'
|
|
78
|
+
Provides-Extra: ollama
|
|
79
|
+
Requires-Dist: langchain-ollama>=0.2.0; extra == 'ollama'
|
|
80
|
+
Provides-Extra: openai
|
|
81
|
+
Requires-Dist: langchain-openai>=0.2.0; extra == 'openai'
|
|
82
|
+
Provides-Extra: openrouter
|
|
83
|
+
Requires-Dist: langchain-openai>=0.2.0; extra == 'openrouter'
|
|
84
|
+
Provides-Extra: rag
|
|
85
|
+
Requires-Dist: chromadb>=0.5.0; extra == 'rag'
|
|
86
|
+
Requires-Dist: langchain-community>=0.3.0; extra == 'rag'
|
|
87
|
+
Requires-Dist: langchain-text-splitters>=0.3.0; extra == 'rag'
|
|
88
|
+
Provides-Extra: server
|
|
89
|
+
Requires-Dist: fastapi>=0.110.0; extra == 'server'
|
|
90
|
+
Requires-Dist: sse-starlette>=2.0.0; extra == 'server'
|
|
91
|
+
Requires-Dist: uvicorn[standard]>=0.29.0; extra == 'server'
|
|
92
|
+
Provides-Extra: vertex
|
|
93
|
+
Requires-Dist: langchain-google-vertexai>=2.0.0; extra == 'vertex'
|
|
94
|
+
Description-Content-Type: text/markdown
|
|
95
|
+
|
|
96
|
+
# 🧬 AgentX-Kit
|
|
97
|
+
|
|
98
|
+
[](https://pypi.org/project/agentx-kit/)
|
|
99
|
+
[](https://pypi.org/project/agentx-kit/)
|
|
100
|
+
[](LICENSE)
|
|
101
|
+
|
|
102
|
+
**A provider-agnostic agentic framework + interactive project scaffolder for LangChain & CrewAI.**
|
|
103
|
+
|
|
104
|
+
Pick your LLM provider (OpenAI, Azure, OpenRouter, Anthropic, Gemini, Vertex AI,
|
|
105
|
+
Bedrock, Groq, Ollama), choose your framework, agents, RAG, memory, MCP tools and
|
|
106
|
+
skills — and AgentX-Kit generates a **ready-to-run project in its own `uv`
|
|
107
|
+
virtual environment**.
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
pip install "agentx-kit[all]"
|
|
111
|
+
agentx new # interactive wizard → scaffolds a uv project
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
> The PyPI distribution is **`agentx-kit`**; the import name and CLI are **`agentx`**
|
|
115
|
+
> (`pip install agentx-kit` → `import agentx` / `agentx --help`).
|
|
116
|
+
|
|
117
|
+
## 📦 Installation
|
|
118
|
+
|
|
119
|
+
### From PyPI (recommended)
|
|
120
|
+
```bash
|
|
121
|
+
pip install agentx-kit # core: CLI + scaffolder + base abstractions
|
|
122
|
+
pip install "agentx-kit[all]" # everything
|
|
123
|
+
```
|
|
124
|
+
Each LLM provider is an **optional extra** so you only pull the SDKs you use:
|
|
125
|
+
```bash
|
|
126
|
+
pip install "agentx-kit[openai,langgraph]" # OpenAI + LangGraph
|
|
127
|
+
pip install "agentx-kit[bedrock,crewai,rag,mcp]" # Bedrock + CrewAI + RAG + MCP
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Using `uv`
|
|
131
|
+
```bash
|
|
132
|
+
uv pip install "agentx-kit[all]"
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### From GitHub (latest, unreleased)
|
|
136
|
+
```bash
|
|
137
|
+
pip install "agentx-kit[all] @ git+https://github.com/muhammadyahiya/agentx-kit.git"
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### From a local clone (development)
|
|
141
|
+
```bash
|
|
142
|
+
git clone https://github.com/muhammadyahiya/agentx-kit.git
|
|
143
|
+
cd agentx-kit
|
|
144
|
+
uv venv && uv pip install -e ".[all,dev]" # or: pip install -e ".[all,dev]"
|
|
145
|
+
pytest -q
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
> Requires **Python 3.10–3.13** and (for the scaffolder's `.venv` creation)
|
|
149
|
+
> [`uv`](https://docs.astral.sh/uv/).
|
|
150
|
+
|
|
151
|
+
### Verify
|
|
152
|
+
```bash
|
|
153
|
+
agentx version
|
|
154
|
+
agentx providers # lists every provider + the env vars it needs
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Why
|
|
158
|
+
- **One factory, every provider.** `get_chat_model("bedrock", ...)` or
|
|
159
|
+
`get_chat_model("openrouter", ...)` — same call, lazy imports, install only
|
|
160
|
+
the extras you use.
|
|
161
|
+
- **Two frameworks.** LangChain/LangGraph *and* CrewAI from the same building blocks.
|
|
162
|
+
- **Batteries included.** RAG, short/long-term memory, MCP tools, and a skills
|
|
163
|
+
registry — each optional and gracefully degrading.
|
|
164
|
+
- **Scaffolder, not a black box.** The generated project is readable, idiomatic
|
|
165
|
+
code you own, pre-wired to your selections, in a fresh `.venv`.
|
|
166
|
+
|
|
167
|
+
## Use as a library
|
|
168
|
+
```python
|
|
169
|
+
from agentx import get_chat_model, list_providers
|
|
170
|
+
|
|
171
|
+
llm = get_chat_model("openai", "gpt-4o-mini")
|
|
172
|
+
print(llm.invoke("Say hi in 3 words").content)
|
|
173
|
+
|
|
174
|
+
for spec in list_providers():
|
|
175
|
+
print(spec.id, "→", spec.label)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
CrewAI:
|
|
179
|
+
```python
|
|
180
|
+
from agentx import get_crewai_llm
|
|
181
|
+
llm = get_crewai_llm("openrouter", "anthropic/claude-3.5-sonnet")
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Scaffold a project
|
|
185
|
+
```bash
|
|
186
|
+
agentx new # fully interactive
|
|
187
|
+
agentx new --name my-bot --yes # accept sensible defaults
|
|
188
|
+
agentx providers # list providers + required env vars
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The wizard asks, one option at a time:
|
|
192
|
+
|
|
193
|
+
1. Project name & target directory
|
|
194
|
+
2. Framework — **LangGraph** or **CrewAI**
|
|
195
|
+
3. LLM **provider** and **model**
|
|
196
|
+
4. Number of **agents** (and their roles)
|
|
197
|
+
5. **RAG** module? (vector store)
|
|
198
|
+
6. **Memory**? (short-term / long-term / both)
|
|
199
|
+
7. **MCP tools**?
|
|
200
|
+
8. **Skills** integration?
|
|
201
|
+
9. **Prompt** style (defaults or scaffolded custom prompts)
|
|
202
|
+
10. Create `.venv` and `uv sync` now?
|
|
203
|
+
|
|
204
|
+
It then renders the project, writes a feature-aware `pyproject.toml` + `.env.example`,
|
|
205
|
+
and runs `uv venv` to create `.venv`.
|
|
206
|
+
|
|
207
|
+
## Prompts: add at creation, or any time after
|
|
208
|
+
Prompts are **not baked into code** — every generated project keeps them in a
|
|
209
|
+
`prompts.json` that `agents.py` loads dynamically. Add an entry and the project
|
|
210
|
+
runs it on next start, **no code changes**.
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
# at creation
|
|
214
|
+
agentx new --yes -n chatops --prompt "You are a senior DevOps engineer. Be terse."
|
|
215
|
+
|
|
216
|
+
# after creation (run inside the project)
|
|
217
|
+
agentx prompt list
|
|
218
|
+
agentx prompt set assistant --text "You are an SRE. Prioritise reliability."
|
|
219
|
+
agentx prompt add reviewer --role "Code Reviewer" --goal "Review diffs" \
|
|
220
|
+
--text "You review code for bugs and security."
|
|
221
|
+
agentx prompt remove reviewer
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
`prompts.json`:
|
|
225
|
+
```json
|
|
226
|
+
{
|
|
227
|
+
"with_rag": false,
|
|
228
|
+
"agents": {
|
|
229
|
+
"assistant": {"role": "...", "goal": "...", "system_prompt": "You are ..."}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
A blank `system_prompt` is auto-derived from the agent's role + goal. You can also
|
|
234
|
+
just open `prompts.json` in an editor — the CLI is a convenience, not a gate.
|
|
235
|
+
|
|
236
|
+
## 🏢 Enterprise pack
|
|
237
|
+
Generate a production-shaped project with one flag — informed by a survey of
|
|
238
|
+
CrewAI/LangGraph/create-llama/AgentStack/agno/pydantic-ai (see [RESEARCH.md](RESEARCH.md)):
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
agentx new --yes -n my-bot --enterprise # everything below
|
|
242
|
+
# or pick individually:
|
|
243
|
+
agentx new --yes -n my-bot --observability --guardrails --serve --docker --ci --evals
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
What `--enterprise` adds to the generated project:
|
|
247
|
+
- **Observability** — OpenTelemetry GenAI tracing + optional Langfuse (`observability.py`), opt-out via `AGENTX_TELEMETRY=false`.
|
|
248
|
+
- **Guardrails** — input/output validation + PII redaction (`guardrails.py`).
|
|
249
|
+
- **FastAPI server** — `server.py` with `/health`, `/chat`, and SSE `/chat/stream`.
|
|
250
|
+
- **Docker** — `Dockerfile` + `docker-compose.yml` (+ `.dockerignore`).
|
|
251
|
+
- **CI** — `.github/workflows/ci.yml` (lint + compile + tests, optional eval gate).
|
|
252
|
+
- **Evals** — `evals/` LLM-as-judge harness runnable locally and in CI.
|
|
253
|
+
- **Typed config** — `config.py` via `pydantic-settings` (12-factor).
|
|
254
|
+
- **Manifest** — `agentx.json` declaring framework, provider, features (à la `langgraph.json`).
|
|
255
|
+
|
|
256
|
+
These are also usable as a **library** in any project:
|
|
257
|
+
```python
|
|
258
|
+
from agentx import (
|
|
259
|
+
setup_tracing, get_callbacks, # observability
|
|
260
|
+
build_resilient_chat, # retries + provider fallbacks
|
|
261
|
+
UsageLimits, UsageTracker, # token/cost budgets
|
|
262
|
+
apply_guards, structured_model, # guardrails + typed outputs
|
|
263
|
+
)
|
|
264
|
+
setup_tracing("my-service")
|
|
265
|
+
llm = build_resilient_chat("openai", "gpt-4o-mini", fallbacks=[("anthropic", "claude-3-5-sonnet-latest")])
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## Installation extras
|
|
269
|
+
| Extra | Installs | For |
|
|
270
|
+
|---|---|---|
|
|
271
|
+
| `openai` / `azure` / `openrouter` | `langchain-openai` | OpenAI-compatible |
|
|
272
|
+
| `anthropic` | `langchain-anthropic` | Claude |
|
|
273
|
+
| `google` | `langchain-google-genai` | Gemini (AI Studio) |
|
|
274
|
+
| `vertex` | `langchain-google-vertexai` | Vertex AI |
|
|
275
|
+
| `bedrock` | `langchain-aws` | Amazon Bedrock |
|
|
276
|
+
| `groq` | `langchain-groq` | Groq |
|
|
277
|
+
| `ollama` | `langchain-ollama` | local |
|
|
278
|
+
| `langgraph` | `langgraph`, `langchain` | LangGraph agents |
|
|
279
|
+
| `crewai` | `crewai` | CrewAI crews |
|
|
280
|
+
| `rag` | `langchain-community`, `chromadb` | RAG |
|
|
281
|
+
| `mcp` | `langchain-mcp-adapters` | MCP tools |
|
|
282
|
+
| `observability` | `opentelemetry-*`, `openinference-*` | tracing |
|
|
283
|
+
| `server` | `fastapi`, `uvicorn` | serving |
|
|
284
|
+
| `all` | everything above | kitchen sink |
|
|
285
|
+
|
|
286
|
+
See [DESIGN.md](DESIGN.md) for the architecture and [RESEARCH.md](RESEARCH.md) for the competitive analysis behind these features.
|
|
287
|
+
|
|
288
|
+
## License
|
|
289
|
+
MIT
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
agentx/__init__.py,sha256=HUgko0a8eqk4KRC4PQtEK_8BplbYCzhHbFMUa_8Nfx0,1422
|
|
2
|
+
agentx/cli.py,sha256=uBogXBaFM11rEwDHO1vvJ0TEDrKQzOoalZ4XhTuvvLg,9869
|
|
3
|
+
agentx/config.py,sha256=7kyJfr2NrKxiBtaxxKjJO0UNsw1C-prg_3Syg9TO5uU,1312
|
|
4
|
+
agentx/guardrails.py,sha256=wYYW-tReK9hW69ulgxJtKjHGqL2tFRhgTNX-nLCAk_U,3015
|
|
5
|
+
agentx/observability.py,sha256=8dt-WUj_pXMydO3_uYztCOQxMnCE1KVEPWekUOdMB5Y,3931
|
|
6
|
+
agentx/reliability.py,sha256=xXLXe2-Br4SmtQ_Id8UoUojDsSDKFrggzTexig6VSqo,4476
|
|
7
|
+
agentx/structured.py,sha256=82ny87Qf8yw2yYBCQ-iQBBj_Kp54xkPyaybsKvEocVg,1354
|
|
8
|
+
agentx/frameworks/__init__.py,sha256=jBfT-uZYs1vA9fAJmwz6GYL6589XAivcHu-YopEtKAI,282
|
|
9
|
+
agentx/frameworks/crewai_agent.py,sha256=H7UQcumr_zAsRdj29frSv2kQSMtkEvoS_Yc2J_ddqkg,1548
|
|
10
|
+
agentx/frameworks/langchain_agent.py,sha256=8E5zNMoHg_uEd_PxvdWOmHi6eaXs9bdxzRCh-Oz-b4M,1514
|
|
11
|
+
agentx/memory/__init__.py,sha256=LbwInW9GLpArre9Y-Zs5puFy_-AwUGwAt4iECYhKRHQ,180
|
|
12
|
+
agentx/memory/store.py,sha256=oQh7B4N723MReibLEhH-dC1FqRUMjBu6EHxgK3HWB-k,2393
|
|
13
|
+
agentx/prompts/__init__.py,sha256=BSqUfXT_u97SKUutNMZ_ND5S8O1cMjIyTRr30POj9Xg,238
|
|
14
|
+
agentx/prompts/templates.py,sha256=LsIBnPsflq1UKRC705tEr9f2gNtOoj3kTqhlLWgRLfw,1312
|
|
15
|
+
agentx/providers/__init__.py,sha256=VFXv5s8qnXpfkJEAFbesxc13h_4I0jnXdxDeTfESUYg,420
|
|
16
|
+
agentx/providers/base.py,sha256=d0GI9LmWA4mICqhoa7e74V6tneCG-o70N73clhW2J9A,1822
|
|
17
|
+
agentx/providers/factory.py,sha256=q9LceEBZfBG5PScA62gzuHXhZUBYmE_z4IQPJew4Ux8,2647
|
|
18
|
+
agentx/providers/registry.py,sha256=tTM48a5zQDOH7CQArQOZh_95kNMNsNENeKIQCVTrpGI,7102
|
|
19
|
+
agentx/rag/__init__.py,sha256=0p-fzaR17q8U4iSaQqh8Ai70gL0qo46EpqO8y5Bp64k,369
|
|
20
|
+
agentx/rag/pipeline.py,sha256=a4sckVrynp52PP1woUBnlWXzd51o83y_ICnSSTa_Auo,4210
|
|
21
|
+
agentx/scaffold/__init__.py,sha256=DJu5mUBfzrp-ySYkck80ck-k2PD3d36t44GnWxQIraU,374
|
|
22
|
+
agentx/scaffold/generator.py,sha256=7NooN2EGUDB59K1XYgtS7VcjHg9vu1ZKr2X5GJeyrbE,7155
|
|
23
|
+
agentx/scaffold/prompts_store.py,sha256=oZHzZCDfm69EY2HcvcD6I59MG1sX6LbCu6ylbgiAhM4,3084
|
|
24
|
+
agentx/scaffold/spec.py,sha256=p-Fx0T-ACF6ELgRjIr-LVLDxyKNn9ZnhCMS4FisbZdg,3002
|
|
25
|
+
agentx/scaffold/wizard.py,sha256=zse6hiPmqTfCFGeQxKojr-2LNT-PTPzAf-8mP-wSIMA,5050
|
|
26
|
+
agentx/scaffold/templates/Dockerfile.j2,sha256=cISw2diE6jjLxeRkEEr569l_zcXFQel8NqAer91mPnM,399
|
|
27
|
+
agentx/scaffold/templates/README.md.j2,sha256=b7WbA8spalUuYNgpHHYls9E3iMzzflKx-7pGVZolpuw,1343
|
|
28
|
+
agentx/scaffold/templates/ci.yml.j2,sha256=O6Ahul7PlIClRah-emM3XbMYiXvCInsPsrNRqvWbw1k,974
|
|
29
|
+
agentx/scaffold/templates/docker-compose.yml.j2,sha256=PAyffd9Du9q_l4x2KeQGb0A6PZNr1FKKOVmO_hJpZ6c,152
|
|
30
|
+
agentx/scaffold/templates/dockerignore.j2,sha256=3J8-k75GHEb3nVMKCu1b9l07H66qYz5a5jYQkRKdHLI,90
|
|
31
|
+
agentx/scaffold/templates/env.example.j2,sha256=VEaveuQk0h97UAmJ2gEJMfFecVxMMc6W3xYe1ycqdxM,323
|
|
32
|
+
agentx/scaffold/templates/gitignore.j2,sha256=BZlrEbYc3EauoEeHLtvlekhwIi16rmrfpVuW9CiOqM8,77
|
|
33
|
+
agentx/scaffold/templates/mcp_servers.json.j2,sha256=klkgZz4OVORg-1SRn5XRKczC3if7Q883eoVzwqBnPq8,141
|
|
34
|
+
agentx/scaffold/templates/pyproject.toml.j2,sha256=TZ-otXEt-CgpI-TRM3B5WknllF9TWkQJmrwIx8HY36s,691
|
|
35
|
+
agentx/scaffold/templates/skills_seed.json.j2,sha256=NpnBET11WJkUogWsZ_DCGZRj4QNy3wYhm5cB9H5c9t0,327
|
|
36
|
+
agentx/scaffold/templates/evals/dataset.json.j2,sha256=f--9wf8_YYvUZ-E-lYYucmOcLbf8httdlc_WkmdnhTs,327
|
|
37
|
+
agentx/scaffold/templates/evals/run_evals.py.j2,sha256=kGLZEM854Wc5Ao656a-TP16AUu_XRseinZ812I677to,2119
|
|
38
|
+
agentx/scaffold/templates/pkg/__init__.py.j2,sha256=iu0vi0VYs7TX64XBiUR4MR1MOBRiQYbjgiYlJuZbDjg,70
|
|
39
|
+
agentx/scaffold/templates/pkg/agents.py.j2,sha256=i3CHAyK5eFXYylRixz8_GGUx5XiOXMmWjq1IIqKf-vc,2499
|
|
40
|
+
agentx/scaffold/templates/pkg/config.py.j2,sha256=sSQdwIbCZjhKvMJFo2SjvHN7iDRWYcQ9qLnVQ0ReQbc,676
|
|
41
|
+
agentx/scaffold/templates/pkg/guardrails.py.j2,sha256=Op4a40FaaKP-OKyQkX5RGDqr1BoBjNvR2DgC4lLMPU4,825
|
|
42
|
+
agentx/scaffold/templates/pkg/main.py.j2,sha256=GV4OtcaJIqGR50iAKJsNiJoUm2eeCbaRvZWfDeB1T1U,2138
|
|
43
|
+
agentx/scaffold/templates/pkg/memory.py.j2,sha256=t7D1csRxdFSABaJthgO8XdQ4YiZANaRLY1HzISUkKYI,568
|
|
44
|
+
agentx/scaffold/templates/pkg/observability.py.j2,sha256=NlTJiz6mQ9L5qhuivEOjzunGXVSF0EHcBqzs2xlFfYM,584
|
|
45
|
+
agentx/scaffold/templates/pkg/prompts.py.j2,sha256=5xy3YmItC_5-8ewftvbImGR4jvJthV0okGxO7JJd7XA,1475
|
|
46
|
+
agentx/scaffold/templates/pkg/rag.py.j2,sha256=NNZJjHzKSOHKH8VeITReDZ0nZziSx5dyB8wtdwhic3U,1092
|
|
47
|
+
agentx/scaffold/templates/pkg/server.py.j2,sha256=CTNu6W2aFOvSA7kGgHTptYfS5X-UUiQdorZp9VfYXBM,2124
|
|
48
|
+
agentx/scaffold/templates/pkg/tools.py.j2,sha256=X4Si0KFMjaJLNW3f-jnsU_SAdy6EMKXqnWIE5zIXS3c,406
|
|
49
|
+
agentx/skills/__init__.py,sha256=bx8wVOU3CYbQfnsOLwIsTJQcXa3K60HaY8ttJTyu3Q4,204
|
|
50
|
+
agentx/skills/registry.py,sha256=ymP4L86fKcCuqfn0kSoC699wu8fJrVfWVPdtInkKREg,2099
|
|
51
|
+
agentx/tools/__init__.py,sha256=J7li3RR5Dh6_nILMSZ8oY3i31UpJgiFWDSAydpjTbdI,182
|
|
52
|
+
agentx/tools/builtin.py,sha256=th_S8ebJpKz4MH7uot0llWSerRoTG2ZaT-57it4jjPo,1539
|
|
53
|
+
agentx/tools/mcp.py,sha256=V63AVWX2rxt1V7rwhTWZ2Ell3zlrZFD07fWVG-wI4H4,1863
|
|
54
|
+
agentx_kit-0.2.0.dist-info/METADATA,sha256=pEtXZpn8Wqy0zkb4LeDLo6nnxu3yqovQlfYkhEwxBSM,11789
|
|
55
|
+
agentx_kit-0.2.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
56
|
+
agentx_kit-0.2.0.dist-info/entry_points.txt,sha256=7vwVzYRgV1cUZLVkt2ULUymznbCarWPw29nUXKdfKG8,42
|
|
57
|
+
agentx_kit-0.2.0.dist-info/licenses/LICENSE,sha256=wWCp0PehBii6IUiqhSmPsyhT6GidoH7zj6uBkfEu1v0,1063
|
|
58
|
+
agentx_kit-0.2.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AgentX
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|