agenttel 0.3.0a1__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 (70) hide show
  1. agenttel-0.3.0a1/.gitignore +38 -0
  2. agenttel-0.3.0a1/PKG-INFO +228 -0
  3. agenttel-0.3.0a1/README.md +182 -0
  4. agenttel-0.3.0a1/pyproject.toml +52 -0
  5. agenttel-0.3.0a1/src/agenttel/__init__.py +13 -0
  6. agenttel-0.3.0a1/src/agenttel/agent/__init__.py +18 -0
  7. agenttel-0.3.0a1/src/agenttel/agent/auth.py +134 -0
  8. agenttel-0.3.0a1/src/agenttel/agent/context.py +86 -0
  9. agenttel-0.3.0a1/src/agenttel/agent/health.py +142 -0
  10. agenttel-0.3.0a1/src/agenttel/agent/identity.py +104 -0
  11. agenttel-0.3.0a1/src/agenttel/agent/incident.py +146 -0
  12. agenttel-0.3.0a1/src/agenttel/agent/mcp_server.py +320 -0
  13. agenttel-0.3.0a1/src/agenttel/agent/remediation.py +167 -0
  14. agenttel-0.3.0a1/src/agenttel/agent/reporting.py +140 -0
  15. agenttel-0.3.0a1/src/agenttel/agentic/__init__.py +5 -0
  16. agenttel-0.3.0a1/src/agenttel/agentic/cost.py +54 -0
  17. agenttel-0.3.0a1/src/agenttel/agentic/guardrail.py +85 -0
  18. agenttel-0.3.0a1/src/agenttel/agentic/orchestration.py +160 -0
  19. agenttel-0.3.0a1/src/agenttel/agentic/quality.py +129 -0
  20. agenttel-0.3.0a1/src/agenttel/agentic/scopes.py +467 -0
  21. agenttel-0.3.0a1/src/agenttel/agentic/tracer.py +161 -0
  22. agenttel-0.3.0a1/src/agenttel/agentic_attributes.py +112 -0
  23. agenttel-0.3.0a1/src/agenttel/anomaly/__init__.py +6 -0
  24. agenttel-0.3.0a1/src/agenttel/anomaly/detector.py +59 -0
  25. agenttel-0.3.0a1/src/agenttel/anomaly/patterns.py +68 -0
  26. agenttel-0.3.0a1/src/agenttel/attributes.py +84 -0
  27. agenttel-0.3.0a1/src/agenttel/baseline/__init__.py +13 -0
  28. agenttel-0.3.0a1/src/agenttel/baseline/composite.py +31 -0
  29. agenttel-0.3.0a1/src/agenttel/baseline/provider.py +42 -0
  30. agenttel-0.3.0a1/src/agenttel/baseline/rolling.py +148 -0
  31. agenttel-0.3.0a1/src/agenttel/causality/__init__.py +5 -0
  32. agenttel-0.3.0a1/src/agenttel/causality/tracker.py +148 -0
  33. agenttel-0.3.0a1/src/agenttel/config.py +197 -0
  34. agenttel-0.3.0a1/src/agenttel/engine.py +161 -0
  35. agenttel-0.3.0a1/src/agenttel/enums.py +198 -0
  36. agenttel-0.3.0a1/src/agenttel/error/__init__.py +5 -0
  37. agenttel-0.3.0a1/src/agenttel/error/classifier.py +71 -0
  38. agenttel-0.3.0a1/src/agenttel/events.py +113 -0
  39. agenttel-0.3.0a1/src/agenttel/fastapi/__init__.py +24 -0
  40. agenttel-0.3.0a1/src/agenttel/fastapi/config.py +63 -0
  41. agenttel-0.3.0a1/src/agenttel/fastapi/decorators.py +91 -0
  42. agenttel-0.3.0a1/src/agenttel/fastapi/middleware.py +114 -0
  43. agenttel-0.3.0a1/src/agenttel/genai/__init__.py +33 -0
  44. agenttel-0.3.0a1/src/agenttel/genai/anthropic.py +145 -0
  45. agenttel-0.3.0a1/src/agenttel/genai/attributes.py +43 -0
  46. agenttel-0.3.0a1/src/agenttel/genai/bedrock.py +125 -0
  47. agenttel-0.3.0a1/src/agenttel/genai/cost.py +91 -0
  48. agenttel-0.3.0a1/src/agenttel/genai/langchain.py +168 -0
  49. agenttel-0.3.0a1/src/agenttel/genai/openai.py +153 -0
  50. agenttel-0.3.0a1/src/agenttel/genai/span_builder.py +127 -0
  51. agenttel-0.3.0a1/src/agenttel/models.py +146 -0
  52. agenttel-0.3.0a1/src/agenttel/processor.py +190 -0
  53. agenttel-0.3.0a1/src/agenttel/slo/__init__.py +5 -0
  54. agenttel-0.3.0a1/src/agenttel/slo/tracker.py +108 -0
  55. agenttel-0.3.0a1/src/agenttel/topology/__init__.py +5 -0
  56. agenttel-0.3.0a1/src/agenttel/topology/registry.py +86 -0
  57. agenttel-0.3.0a1/tests/conftest.py +22 -0
  58. agenttel-0.3.0a1/tests/test_agent.py +116 -0
  59. agenttel-0.3.0a1/tests/test_agentic.py +84 -0
  60. agenttel-0.3.0a1/tests/test_anomaly.py +85 -0
  61. agenttel-0.3.0a1/tests/test_attributes.py +63 -0
  62. agenttel-0.3.0a1/tests/test_baseline.py +145 -0
  63. agenttel-0.3.0a1/tests/test_fastapi.py +20 -0
  64. agenttel-0.3.0a1/tests/test_genai.py +47 -0
  65. agenttel-0.3.0a1/tests/test_genai_anthropic.py +155 -0
  66. agenttel-0.3.0a1/tests/test_genai_openai.py +182 -0
  67. agenttel-0.3.0a1/tests/test_mcp_server.py +136 -0
  68. agenttel-0.3.0a1/tests/test_processor.py +44 -0
  69. agenttel-0.3.0a1/tests/test_slo.py +70 -0
  70. agenttel-0.3.0a1/tests/test_topology.py +148 -0
@@ -0,0 +1,38 @@
1
+ # Gradle
2
+ .gradle/
3
+ build/
4
+ !gradle/wrapper/gradle-wrapper.jar
5
+
6
+ # IDE
7
+ .idea/
8
+ *.iml
9
+ .vscode/
10
+ .settings/
11
+ .classpath
12
+ .project
13
+ .factorypath
14
+
15
+ # OS
16
+ .DS_Store
17
+ Thumbs.db
18
+
19
+ # MkDocs build output
20
+ site/
21
+
22
+ # Node.js
23
+ node_modules/
24
+ dist/
25
+
26
+ # Python
27
+ __pycache__/
28
+ *.pyc
29
+ *.py[cod]
30
+ *.egg-info/
31
+ *.egg
32
+ .venv/
33
+ .pytest_cache/
34
+
35
+ # Secrets
36
+ .env
37
+ *.key
38
+ *.pem
@@ -0,0 +1,228 @@
1
+ Metadata-Version: 2.4
2
+ Name: agenttel
3
+ Version: 0.3.0a1
4
+ Summary: AgentTel Python SDK — AI-native telemetry for Python services
5
+ Author-email: AgentTel <engineering@agenttel.io>
6
+ License-Expression: Apache-2.0
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Framework :: FastAPI
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Topic :: System :: Monitoring
14
+ Requires-Python: >=3.11
15
+ Requires-Dist: opentelemetry-api>=1.20.0
16
+ Requires-Dist: opentelemetry-sdk>=1.20.0
17
+ Requires-Dist: pydantic>=2.0
18
+ Requires-Dist: pyyaml>=6.0
19
+ Provides-Extra: agent
20
+ Requires-Dist: aiohttp>=3.9; extra == 'agent'
21
+ Provides-Extra: all
22
+ Requires-Dist: aiohttp>=3.9; extra == 'all'
23
+ Requires-Dist: anthropic>=0.20; extra == 'all'
24
+ Requires-Dist: boto3>=1.28; extra == 'all'
25
+ Requires-Dist: fastapi>=0.100.0; extra == 'all'
26
+ Requires-Dist: langchain-core>=0.1; extra == 'all'
27
+ Requires-Dist: openai>=1.0; extra == 'all'
28
+ Requires-Dist: opentelemetry-instrumentation-fastapi>=0.41b0; extra == 'all'
29
+ Provides-Extra: anthropic
30
+ Requires-Dist: anthropic>=0.20; extra == 'anthropic'
31
+ Provides-Extra: bedrock
32
+ Requires-Dist: boto3>=1.28; extra == 'bedrock'
33
+ Provides-Extra: dev
34
+ Requires-Dist: httpx>=0.24; extra == 'dev'
35
+ Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
36
+ Requires-Dist: pytest>=7.0; extra == 'dev'
37
+ Requires-Dist: respx>=0.20; extra == 'dev'
38
+ Provides-Extra: fastapi
39
+ Requires-Dist: fastapi>=0.100.0; extra == 'fastapi'
40
+ Requires-Dist: opentelemetry-instrumentation-fastapi>=0.41b0; extra == 'fastapi'
41
+ Provides-Extra: langchain
42
+ Requires-Dist: langchain-core>=0.1; extra == 'langchain'
43
+ Provides-Extra: openai
44
+ Requires-Dist: openai>=1.0; extra == 'openai'
45
+ Description-Content-Type: text/markdown
46
+
47
+ # AgentTel Python SDK
48
+
49
+ AI-native telemetry SDK for Python services. Full feature parity with the JVM SDK — semantic attributes, baselines, anomaly detection, SLO tracking, GenAI instrumentation, agentic observability, and MCP agent interface.
50
+
51
+ ## Installation
52
+
53
+ ```bash
54
+ pip install agenttel
55
+
56
+ # With extras
57
+ pip install agenttel[fastapi] # FastAPI middleware + auto-config
58
+ pip install agenttel[openai] # OpenAI instrumentation
59
+ pip install agenttel[anthropic] # Anthropic instrumentation
60
+ pip install agenttel[langchain] # LangChain instrumentation
61
+ pip install agenttel[bedrock] # AWS Bedrock instrumentation
62
+ pip install agenttel[agent] # MCP server (aiohttp)
63
+ pip install agenttel[all] # Everything
64
+ ```
65
+
66
+ ## Quick Start (FastAPI)
67
+
68
+ ### 1. Create `agenttel.yml`
69
+
70
+ ```yaml
71
+ agenttel:
72
+ enabled: true
73
+ topology:
74
+ team: payments
75
+ tier: critical
76
+ domain: fintech
77
+ on-call-channel: "#payments-oncall"
78
+ dependencies:
79
+ - name: postgres
80
+ type: database
81
+ criticality: required
82
+ timeout-ms: 3000
83
+ - name: stripe-api
84
+ type: external_api
85
+ criticality: degraded
86
+ timeout-ms: 5000
87
+ circuit-breaker: true
88
+ operations:
89
+ "[POST /api/transfers]":
90
+ profile: critical-write
91
+ expected-latency-p50: "80ms"
92
+ expected-latency-p99: "300ms"
93
+ expected-error-rate: 0.002
94
+ runbook-url: "https://wiki.example.com/runbooks/transfers"
95
+ profiles:
96
+ critical-write:
97
+ retryable: false
98
+ idempotent: false
99
+ escalation-level: page_oncall
100
+ safe-to-restart: false
101
+ baselines:
102
+ rolling-window-size: 1000
103
+ rolling-min-samples: 10
104
+ anomaly-detection:
105
+ enabled: true
106
+ z-score-threshold: 3.0
107
+ ```
108
+
109
+ ### 2. Instrument Your App
110
+
111
+ ```python
112
+ from fastapi import FastAPI
113
+ from agenttel.fastapi import instrument_fastapi
114
+
115
+ app = FastAPI()
116
+ engine = instrument_fastapi(app)
117
+
118
+ @app.post("/api/transfers")
119
+ async def create_transfer(request: dict):
120
+ # Your spans automatically get AgentTel enrichment:
121
+ # - topology attributes (team, tier, domain)
122
+ # - operation context (retryable, runbook, escalation)
123
+ # - baseline attributes (P50, P99, error rate)
124
+ # - anomaly detection on span end
125
+ # - SLO budget tracking
126
+ return {"status": "completed"}
127
+ ```
128
+
129
+ ### 3. Use the Decorator
130
+
131
+ ```python
132
+ from agenttel.fastapi import agent_operation
133
+
134
+ @app.get("/api/accounts/{account_id}")
135
+ @agent_operation(
136
+ expected_latency_p50="10ms",
137
+ expected_latency_p99="50ms",
138
+ retryable=True,
139
+ runbook_url="https://wiki.example.com/runbooks/get-account",
140
+ )
141
+ async def get_account(account_id: str):
142
+ return {"id": account_id}
143
+ ```
144
+
145
+ ## GenAI Instrumentation
146
+
147
+ ```python
148
+ from openai import OpenAI
149
+ from agenttel.genai import instrument_openai
150
+
151
+ client = instrument_openai(OpenAI())
152
+
153
+ # All completions are now traced with:
154
+ # - gen_ai.system, gen_ai.request.model
155
+ # - gen_ai.usage.input_tokens, gen_ai.usage.output_tokens
156
+ # - agenttel.genai.cost_usd
157
+ response = client.chat.completions.create(
158
+ model="gpt-4o",
159
+ messages=[{"role": "user", "content": "Hello"}],
160
+ )
161
+ ```
162
+
163
+ Anthropic, LangChain, and AWS Bedrock are also supported:
164
+
165
+ ```python
166
+ from anthropic import Anthropic
167
+ from agenttel.genai import instrument_anthropic, instrument_langchain
168
+
169
+ client = instrument_anthropic(Anthropic())
170
+ instrument_langchain() # Global LangChain instrumentation
171
+ ```
172
+
173
+ ## Agentic Observability
174
+
175
+ ```python
176
+ from agenttel.agentic import AgentTracer
177
+ from agenttel.enums import AgentType, StepType
178
+
179
+ tracer = (AgentTracer.create()
180
+ .agent_name("incident-responder")
181
+ .agent_type(AgentType.SINGLE)
182
+ .framework("langchain")
183
+ .build())
184
+
185
+ with tracer.invoke("diagnose high latency") as invocation:
186
+ with invocation.step(StepType.THOUGHT, "analyzing metrics"):
187
+ pass # reasoning
188
+
189
+ with invocation.tool_call("get_service_health") as tool:
190
+ result = {"status": "degraded"}
191
+ tool.set_result(result)
192
+
193
+ with invocation.task("check dependencies") as task:
194
+ with task.step(StepType.ACTION, "querying deps"):
195
+ pass
196
+
197
+ invocation.complete(goal_achieved=True)
198
+ ```
199
+
200
+ ## Architecture
201
+
202
+ ```
203
+ agenttel-python/
204
+ ├── src/agenttel/
205
+ │ ├── attributes.py # Semantic attribute constants
206
+ │ ├── enums.py # All enums (ServiceTier, ErrorCategory, etc.)
207
+ │ ├── models.py # Pydantic data models
208
+ │ ├── config.py # YAML config loader
209
+ │ ├── processor.py # OTel SpanProcessor
210
+ │ ├── engine.py # High-level orchestrator
211
+ │ ├── baseline/ # Static, rolling, composite baselines
212
+ │ ├── anomaly/ # Z-score anomaly detection + pattern matching
213
+ │ ├── slo/ # SLO tracking with error budgets
214
+ │ ├── error/ # Error classification
215
+ │ ├── causality/ # Dependency state tracking
216
+ │ ├── topology/ # Service topology registry
217
+ │ ├── fastapi/ # FastAPI middleware + decorators
218
+ │ ├── genai/ # OpenAI, Anthropic, LangChain, Bedrock wrappers
219
+ │ ├── agent/ # MCP server, health aggregation, identity
220
+ │ └── agentic/ # AgentTracer, scopes, orchestration patterns
221
+ └── tests/
222
+ ```
223
+
224
+ ## Requirements
225
+
226
+ - Python 3.11+
227
+ - OpenTelemetry SDK 1.20+
228
+ - Pydantic 2.0+
@@ -0,0 +1,182 @@
1
+ # AgentTel Python SDK
2
+
3
+ AI-native telemetry SDK for Python services. Full feature parity with the JVM SDK — semantic attributes, baselines, anomaly detection, SLO tracking, GenAI instrumentation, agentic observability, and MCP agent interface.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install agenttel
9
+
10
+ # With extras
11
+ pip install agenttel[fastapi] # FastAPI middleware + auto-config
12
+ pip install agenttel[openai] # OpenAI instrumentation
13
+ pip install agenttel[anthropic] # Anthropic instrumentation
14
+ pip install agenttel[langchain] # LangChain instrumentation
15
+ pip install agenttel[bedrock] # AWS Bedrock instrumentation
16
+ pip install agenttel[agent] # MCP server (aiohttp)
17
+ pip install agenttel[all] # Everything
18
+ ```
19
+
20
+ ## Quick Start (FastAPI)
21
+
22
+ ### 1. Create `agenttel.yml`
23
+
24
+ ```yaml
25
+ agenttel:
26
+ enabled: true
27
+ topology:
28
+ team: payments
29
+ tier: critical
30
+ domain: fintech
31
+ on-call-channel: "#payments-oncall"
32
+ dependencies:
33
+ - name: postgres
34
+ type: database
35
+ criticality: required
36
+ timeout-ms: 3000
37
+ - name: stripe-api
38
+ type: external_api
39
+ criticality: degraded
40
+ timeout-ms: 5000
41
+ circuit-breaker: true
42
+ operations:
43
+ "[POST /api/transfers]":
44
+ profile: critical-write
45
+ expected-latency-p50: "80ms"
46
+ expected-latency-p99: "300ms"
47
+ expected-error-rate: 0.002
48
+ runbook-url: "https://wiki.example.com/runbooks/transfers"
49
+ profiles:
50
+ critical-write:
51
+ retryable: false
52
+ idempotent: false
53
+ escalation-level: page_oncall
54
+ safe-to-restart: false
55
+ baselines:
56
+ rolling-window-size: 1000
57
+ rolling-min-samples: 10
58
+ anomaly-detection:
59
+ enabled: true
60
+ z-score-threshold: 3.0
61
+ ```
62
+
63
+ ### 2. Instrument Your App
64
+
65
+ ```python
66
+ from fastapi import FastAPI
67
+ from agenttel.fastapi import instrument_fastapi
68
+
69
+ app = FastAPI()
70
+ engine = instrument_fastapi(app)
71
+
72
+ @app.post("/api/transfers")
73
+ async def create_transfer(request: dict):
74
+ # Your spans automatically get AgentTel enrichment:
75
+ # - topology attributes (team, tier, domain)
76
+ # - operation context (retryable, runbook, escalation)
77
+ # - baseline attributes (P50, P99, error rate)
78
+ # - anomaly detection on span end
79
+ # - SLO budget tracking
80
+ return {"status": "completed"}
81
+ ```
82
+
83
+ ### 3. Use the Decorator
84
+
85
+ ```python
86
+ from agenttel.fastapi import agent_operation
87
+
88
+ @app.get("/api/accounts/{account_id}")
89
+ @agent_operation(
90
+ expected_latency_p50="10ms",
91
+ expected_latency_p99="50ms",
92
+ retryable=True,
93
+ runbook_url="https://wiki.example.com/runbooks/get-account",
94
+ )
95
+ async def get_account(account_id: str):
96
+ return {"id": account_id}
97
+ ```
98
+
99
+ ## GenAI Instrumentation
100
+
101
+ ```python
102
+ from openai import OpenAI
103
+ from agenttel.genai import instrument_openai
104
+
105
+ client = instrument_openai(OpenAI())
106
+
107
+ # All completions are now traced with:
108
+ # - gen_ai.system, gen_ai.request.model
109
+ # - gen_ai.usage.input_tokens, gen_ai.usage.output_tokens
110
+ # - agenttel.genai.cost_usd
111
+ response = client.chat.completions.create(
112
+ model="gpt-4o",
113
+ messages=[{"role": "user", "content": "Hello"}],
114
+ )
115
+ ```
116
+
117
+ Anthropic, LangChain, and AWS Bedrock are also supported:
118
+
119
+ ```python
120
+ from anthropic import Anthropic
121
+ from agenttel.genai import instrument_anthropic, instrument_langchain
122
+
123
+ client = instrument_anthropic(Anthropic())
124
+ instrument_langchain() # Global LangChain instrumentation
125
+ ```
126
+
127
+ ## Agentic Observability
128
+
129
+ ```python
130
+ from agenttel.agentic import AgentTracer
131
+ from agenttel.enums import AgentType, StepType
132
+
133
+ tracer = (AgentTracer.create()
134
+ .agent_name("incident-responder")
135
+ .agent_type(AgentType.SINGLE)
136
+ .framework("langchain")
137
+ .build())
138
+
139
+ with tracer.invoke("diagnose high latency") as invocation:
140
+ with invocation.step(StepType.THOUGHT, "analyzing metrics"):
141
+ pass # reasoning
142
+
143
+ with invocation.tool_call("get_service_health") as tool:
144
+ result = {"status": "degraded"}
145
+ tool.set_result(result)
146
+
147
+ with invocation.task("check dependencies") as task:
148
+ with task.step(StepType.ACTION, "querying deps"):
149
+ pass
150
+
151
+ invocation.complete(goal_achieved=True)
152
+ ```
153
+
154
+ ## Architecture
155
+
156
+ ```
157
+ agenttel-python/
158
+ ├── src/agenttel/
159
+ │ ├── attributes.py # Semantic attribute constants
160
+ │ ├── enums.py # All enums (ServiceTier, ErrorCategory, etc.)
161
+ │ ├── models.py # Pydantic data models
162
+ │ ├── config.py # YAML config loader
163
+ │ ├── processor.py # OTel SpanProcessor
164
+ │ ├── engine.py # High-level orchestrator
165
+ │ ├── baseline/ # Static, rolling, composite baselines
166
+ │ ├── anomaly/ # Z-score anomaly detection + pattern matching
167
+ │ ├── slo/ # SLO tracking with error budgets
168
+ │ ├── error/ # Error classification
169
+ │ ├── causality/ # Dependency state tracking
170
+ │ ├── topology/ # Service topology registry
171
+ │ ├── fastapi/ # FastAPI middleware + decorators
172
+ │ ├── genai/ # OpenAI, Anthropic, LangChain, Bedrock wrappers
173
+ │ ├── agent/ # MCP server, health aggregation, identity
174
+ │ └── agentic/ # AgentTracer, scopes, orchestration patterns
175
+ └── tests/
176
+ ```
177
+
178
+ ## Requirements
179
+
180
+ - Python 3.11+
181
+ - OpenTelemetry SDK 1.20+
182
+ - Pydantic 2.0+
@@ -0,0 +1,52 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "agenttel"
7
+ version = "0.3.0a1"
8
+ description = "AgentTel Python SDK — AI-native telemetry for Python services"
9
+ readme = "README.md"
10
+ license = "Apache-2.0"
11
+ requires-python = ">=3.11"
12
+ authors = [{ name = "AgentTel", email = "engineering@agenttel.io" }]
13
+ classifiers = [
14
+ "Development Status :: 3 - Alpha",
15
+ "Intended Audience :: Developers",
16
+ "Programming Language :: Python :: 3.11",
17
+ "Programming Language :: Python :: 3.12",
18
+ "Programming Language :: Python :: 3.13",
19
+ "Topic :: System :: Monitoring",
20
+ "Framework :: FastAPI",
21
+ ]
22
+ dependencies = [
23
+ "opentelemetry-api>=1.20.0",
24
+ "opentelemetry-sdk>=1.20.0",
25
+ "pydantic>=2.0",
26
+ "pyyaml>=6.0",
27
+ ]
28
+
29
+ [project.optional-dependencies]
30
+ fastapi = ["fastapi>=0.100.0", "opentelemetry-instrumentation-fastapi>=0.41b0"]
31
+ openai = ["openai>=1.0"]
32
+ anthropic = ["anthropic>=0.20"]
33
+ langchain = ["langchain-core>=0.1"]
34
+ bedrock = ["boto3>=1.28"]
35
+ agent = ["aiohttp>=3.9"]
36
+ all = ["agenttel[fastapi,openai,anthropic,langchain,bedrock,agent]"]
37
+ dev = [
38
+ "pytest>=7.0",
39
+ "pytest-asyncio>=0.21",
40
+ "httpx>=0.24",
41
+ "respx>=0.20",
42
+ ]
43
+
44
+ [project.entry-points."opentelemetry_traces"]
45
+ agenttel = "agenttel:AgentTelSpanProcessor"
46
+
47
+ [tool.hatch.build.targets.wheel]
48
+ packages = ["src/agenttel"]
49
+
50
+ [tool.pytest.ini_options]
51
+ testpaths = ["tests"]
52
+ asyncio_mode = "auto"
@@ -0,0 +1,13 @@
1
+ """AgentTel Python SDK — AI-native telemetry for Python services."""
2
+
3
+ from agenttel.config import AgentTelConfig
4
+ from agenttel.engine import AgentTelEngine
5
+ from agenttel.processor import AgentTelSpanProcessor
6
+
7
+ __all__ = [
8
+ "AgentTelConfig",
9
+ "AgentTelEngine",
10
+ "AgentTelSpanProcessor",
11
+ ]
12
+
13
+ __version__ = "0.3.0-alpha"
@@ -0,0 +1,18 @@
1
+ """Agent interface for AgentTel (MCP server, health, identity, incident)."""
2
+
3
+ from agenttel.agent.auth import (
4
+ AuthConfig,
5
+ ToolPermission,
6
+ ToolPermissionRegistry as AuthPermissionRegistry,
7
+ )
8
+ from agenttel.agent.health import ServiceHealthAggregator
9
+ from agenttel.agent.identity import AgentIdentity, ToolPermissionRegistry
10
+
11
+ __all__ = [
12
+ "AuthConfig",
13
+ "AuthPermissionRegistry",
14
+ "ServiceHealthAggregator",
15
+ "AgentIdentity",
16
+ "ToolPermission",
17
+ "ToolPermissionRegistry",
18
+ ]
@@ -0,0 +1,134 @@
1
+ """API key authentication and role-based permissions for the MCP server.
2
+
3
+ Opt-in: when no AuthConfig is provided, all checks are skipped
4
+ and the server behaves as before (backward compatible).
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from dataclasses import dataclass
10
+ from enum import Enum
11
+ from typing import Callable
12
+
13
+
14
+ class ToolPermission(Enum):
15
+ """Permission levels for MCP tool access."""
16
+
17
+ READ = "read"
18
+ DIAGNOSE = "diagnose"
19
+ REMEDIATE = "remediate"
20
+ ADMIN = "admin"
21
+
22
+
23
+ @dataclass
24
+ class AgentIdentity:
25
+ """Identifies an authenticated agent making MCP requests."""
26
+
27
+ agent_id: str
28
+ role: str
29
+ session_id: str | None = None
30
+
31
+
32
+ @dataclass
33
+ class AuthConfig:
34
+ """Configuration for API key authentication.
35
+
36
+ Provide either a static api_keys map, a custom validate_key function,
37
+ or both. When both are provided, the static map is checked first.
38
+ """
39
+
40
+ api_keys: dict[str, AgentIdentity] | None = None
41
+ validate_key: Callable[[str], AgentIdentity | None] | None = None
42
+
43
+ def resolve_key(self, key: str) -> AgentIdentity | None:
44
+ """Resolve a bearer token to an agent identity.
45
+
46
+ Returns None if the key is invalid or not found.
47
+ """
48
+ trimmed = key.strip()
49
+ if not trimmed:
50
+ return None
51
+
52
+ if self.api_keys:
53
+ identity = self.api_keys.get(trimmed)
54
+ if identity is not None:
55
+ return identity
56
+
57
+ if self.validate_key:
58
+ return self.validate_key(trimmed)
59
+
60
+ return None
61
+
62
+
63
+ # Default role-to-permission mappings
64
+ _DEFAULT_ROLE_PERMISSIONS: dict[str, set[ToolPermission]] = {
65
+ "observer": {ToolPermission.READ},
66
+ "diagnostician": {ToolPermission.READ, ToolPermission.DIAGNOSE},
67
+ "remediator": {ToolPermission.READ, ToolPermission.DIAGNOSE, ToolPermission.REMEDIATE},
68
+ "admin": {ToolPermission.READ, ToolPermission.DIAGNOSE, ToolPermission.REMEDIATE, ToolPermission.ADMIN},
69
+ }
70
+
71
+ # Default tool-to-required-permission mappings
72
+ _DEFAULT_TOOL_PERMISSIONS: dict[str, ToolPermission] = {
73
+ # READ tools
74
+ "get_service_health": ToolPermission.READ,
75
+ "get_operation_baselines": ToolPermission.READ,
76
+ "get_anomalies": ToolPermission.READ,
77
+ "get_slo_status": ToolPermission.READ,
78
+ "get_dependency_health": ToolPermission.READ,
79
+ "get_topology": ToolPermission.READ,
80
+ "get_incident_context": ToolPermission.READ,
81
+ "get_error_classification": ToolPermission.READ,
82
+ "get_deployment_info": ToolPermission.READ,
83
+ "get_slo_report": ToolPermission.READ,
84
+ "get_executive_summary": ToolPermission.READ,
85
+ "get_trend_analysis": ToolPermission.READ,
86
+ "get_playbook": ToolPermission.READ,
87
+ "get_session": ToolPermission.READ,
88
+ # DIAGNOSE tools
89
+ "verify_remediation_effect": ToolPermission.DIAGNOSE,
90
+ "create_session": ToolPermission.DIAGNOSE,
91
+ "add_session_entry": ToolPermission.DIAGNOSE,
92
+ "suggest_remediation": ToolPermission.DIAGNOSE,
93
+ "get_change_correlation": ToolPermission.DIAGNOSE,
94
+ # REMEDIATE tools
95
+ "execute_remediation": ToolPermission.REMEDIATE,
96
+ "list_remediation_actions": ToolPermission.REMEDIATE,
97
+ }
98
+
99
+
100
+ class ToolPermissionRegistry:
101
+ """Maps roles to granted permissions and tools to required permission levels.
102
+
103
+ Pre-populated with sensible defaults:
104
+ observer -> [READ]
105
+ diagnostician -> [READ, DIAGNOSE]
106
+ remediator -> [READ, DIAGNOSE, REMEDIATE]
107
+ admin -> [READ, DIAGNOSE, REMEDIATE, ADMIN]
108
+ """
109
+
110
+ def __init__(self) -> None:
111
+ self._role_permissions: dict[str, set[ToolPermission]] = {
112
+ k: set(v) for k, v in _DEFAULT_ROLE_PERMISSIONS.items()
113
+ }
114
+ self._tool_permissions: dict[str, ToolPermission] = dict(_DEFAULT_TOOL_PERMISSIONS)
115
+
116
+ def set_role_permissions(self, role: str, perms: list[ToolPermission]) -> None:
117
+ """Set the permissions granted to a role, replacing any existing mapping."""
118
+ self._role_permissions[role.lower()] = set(perms)
119
+
120
+ def set_tool_permission(self, tool_name: str, perm: ToolPermission) -> None:
121
+ """Set the required permission level for a specific tool."""
122
+ self._tool_permissions[tool_name] = perm
123
+
124
+ def is_allowed(self, identity: AgentIdentity, tool_name: str) -> bool:
125
+ """Check whether the given identity has permission to invoke the named tool.
126
+
127
+ Unknown tools default to READ. Unknown roles get observer permissions.
128
+ """
129
+ role = identity.role.lower()
130
+ granted = self._role_permissions.get(
131
+ role, self._role_permissions.get("observer", {ToolPermission.READ})
132
+ )
133
+ required = self._tool_permissions.get(tool_name, ToolPermission.READ)
134
+ return required in granted