idun-agent-engine 0.3.9__tar.gz → 0.4.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 (92) hide show
  1. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/PKG-INFO +12 -8
  2. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/README.md +3 -3
  3. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/pyproject.toml +18 -6
  4. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/_version.py +1 -1
  5. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/agent/adk/adk.py +5 -2
  6. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/agent/langgraph/langgraph.py +1 -1
  7. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/core/config_builder.py +11 -5
  8. idun_agent_engine-0.4.1/src/idun_agent_engine/guardrails/guardrails_hub/__init__.py +5 -0
  9. idun_agent_engine-0.4.1/src/idun_agent_engine/mcp/__init__.py +21 -0
  10. idun_agent_engine-0.4.1/src/idun_agent_engine/mcp/helpers.py +189 -0
  11. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/mcp/registry.py +7 -1
  12. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/server/lifespan.py +22 -0
  13. idun_agent_engine-0.4.1/src/idun_agent_engine/telemetry/__init__.py +19 -0
  14. idun_agent_engine-0.4.1/src/idun_agent_engine/telemetry/config.py +29 -0
  15. idun_agent_engine-0.4.1/src/idun_agent_engine/telemetry/telemetry.py +248 -0
  16. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_platform_cli/groups/agent/package.py +3 -0
  17. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_platform_cli/groups/agent/serve.py +2 -0
  18. idun_agent_engine-0.4.1/src/idun_platform_cli/groups/init.py +25 -0
  19. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_platform_cli/main.py +3 -0
  20. idun_agent_engine-0.4.1/src/idun_platform_cli/telemetry.py +54 -0
  21. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/__init__.py +0 -0
  22. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/css/__init__.py +0 -0
  23. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/css/create_agent.py +912 -0
  24. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/css/main.py +89 -0
  25. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/main.py +87 -0
  26. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/schemas/__init__.py +0 -0
  27. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/schemas/create_agent.py +60 -0
  28. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/screens/__init__.py +0 -0
  29. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/screens/create_agent.py +622 -0
  30. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/utils/__init__.py +0 -0
  31. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/utils/config.py +182 -0
  32. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/validators/__init__.py +0 -0
  33. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/validators/guardrails.py +88 -0
  34. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/validators/mcps.py +84 -0
  35. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/validators/observability.py +65 -0
  36. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/widgets/__init__.py +19 -0
  37. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/widgets/chat_widget.py +153 -0
  38. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/widgets/guardrails_widget.py +356 -0
  39. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/widgets/identity_widget.py +252 -0
  40. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/widgets/mcps_widget.py +230 -0
  41. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/widgets/memory_widget.py +195 -0
  42. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/widgets/observability_widget.py +382 -0
  43. idun_agent_engine-0.4.1/src/idun_platform_cli/tui/widgets/serve_widget.py +82 -0
  44. idun_agent_engine-0.3.9/src/idun_agent_engine/guardrails/guardrails_hub/__init__.py +0 -5
  45. idun_agent_engine-0.3.9/src/idun_agent_engine/mcp/__init__.py +0 -5
  46. idun_agent_engine-0.3.9/src/idun_agent_engine/mcp/helpers.py +0 -97
  47. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/.gitignore +0 -0
  48. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/__init__.py +0 -0
  49. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/agent/__init__.py +0 -0
  50. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/agent/adk/__init__.py +0 -0
  51. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/agent/base.py +0 -0
  52. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/agent/haystack/__init__.py +0 -0
  53. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/agent/haystack/haystack.py +0 -0
  54. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/agent/haystack/haystack_model.py +0 -0
  55. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/agent/haystack/utils.py +0 -0
  56. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/agent/langgraph/__init__.py +0 -0
  57. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/core/__init__.py +0 -0
  58. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/core/app_factory.py +1 -1
  59. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/core/engine_config.py +0 -0
  60. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/core/server_runner.py +0 -0
  61. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/guardrails/__init__.py +0 -0
  62. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/guardrails/base.py +0 -0
  63. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/guardrails/guardrails_hub/guardrails_hub.py +0 -0
  64. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/guardrails/guardrails_hub/utils.py +0 -0
  65. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/observability/__init__.py +0 -0
  66. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/observability/base.py +0 -0
  67. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/observability/gcp_logging/__init__.py +0 -0
  68. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/observability/gcp_logging/gcp_logging_handler.py +0 -0
  69. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/observability/gcp_trace/__init__.py +0 -0
  70. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/observability/gcp_trace/gcp_trace_handler.py +0 -0
  71. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/observability/langfuse/__init__.py +0 -0
  72. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/observability/langfuse/langfuse_handler.py +0 -0
  73. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/observability/phoenix/__init__.py +0 -0
  74. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/observability/phoenix/phoenix_handler.py +0 -0
  75. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/observability/phoenix_local/__init__.py +0 -0
  76. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/observability/phoenix_local/phoenix_local_handler.py +0 -0
  77. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/py.typed +0 -0
  78. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/server/__init__.py +0 -0
  79. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/server/dependencies.py +0 -0
  80. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/server/routers/__init__.py +0 -0
  81. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/server/routers/agent.py +0 -0
  82. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/server/routers/agui.py +0 -0
  83. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/server/routers/base.py +0 -0
  84. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/server/server_config.py +0 -0
  85. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/templates/__init__.py +0 -0
  86. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/templates/correction.py +0 -0
  87. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/templates/deep_research.py +0 -0
  88. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_agent_engine/templates/translation.py +0 -0
  89. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_platform_cli/__init__.py +0 -0
  90. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_platform_cli/groups/__init__.py +0 -0
  91. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_platform_cli/groups/agent/__init__.py +0 -0
  92. {idun_agent_engine-0.3.9 → idun_agent_engine-0.4.1}/src/idun_platform_cli/groups/agent/main.py +0 -0
@@ -1,17 +1,17 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: idun-agent-engine
3
- Version: 0.3.9
3
+ Version: 0.4.1
4
4
  Summary: Python SDK and runtime to serve AI agents with FastAPI, LangGraph, and observability.
5
5
  Project-URL: Homepage, https://github.com/geoffreyharrazi/idun-agent-platform
6
6
  Project-URL: Repository, https://github.com/geoffreyharrazi/idun-agent-platform
7
7
  Project-URL: Documentation, https://github.com/geoffreyharrazi/idun-agent-platform/tree/main/libs/idun_agent_engine
8
8
  Project-URL: Issues, https://github.com/geoffreyharrazi/idun-agent-platform/issues
9
9
  Author-email: Geoffrey HARRAZI <geoffreyharrazi@gmail.com>
10
- License-Expression: MIT
10
+ License-Expression: GPL-3.0-only
11
11
  Keywords: agents,fastapi,langgraph,llm,observability,sdk
12
12
  Classifier: Framework :: FastAPI
13
13
  Classifier: Intended Audience :: Developers
14
- Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
15
15
  Classifier: Programming Language :: Python :: 3
16
16
  Classifier: Programming Language :: Python :: 3 :: Only
17
17
  Classifier: Programming Language :: Python :: 3.12
@@ -31,12 +31,12 @@ Requires-Dist: deepagents<1.0.0,>=0.2.8
31
31
  Requires-Dist: fastapi<0.116.0,>=0.115.0
32
32
  Requires-Dist: google-adk<2.0.0,>=1.19.0
33
33
  Requires-Dist: google-cloud-logging<4.0.0,>=3.10.0
34
- Requires-Dist: guardrails-ai<0.8.0,>=0.7.0
34
+ Requires-Dist: guardrails-ai<0.8.0,>=0.7.2
35
35
  Requires-Dist: httpx<0.29.0,>=0.28.1
36
36
  Requires-Dist: idun-agent-schema<1.0.0,>=0.3.8
37
37
  Requires-Dist: langchain-core<2.0.0,>=1.0.0
38
38
  Requires-Dist: langchain-google-vertexai<4.0.0,>=2.0.27
39
- Requires-Dist: langchain-mcp-adapters<0.2.0,>=0.1.0
39
+ Requires-Dist: langchain-mcp-adapters<0.3.0,>=0.2.0
40
40
  Requires-Dist: langchain<2.0.0,>=1.0.0
41
41
  Requires-Dist: langfuse-haystack>=2.3.0
42
42
  Requires-Dist: langfuse<4.0.0,>=2.60.8
@@ -51,12 +51,16 @@ Requires-Dist: openinference-instrumentation-mcp<2.0.0,>=1.0.0
51
51
  Requires-Dist: openinference-instrumentation-vertexai<1.0.0,>=0.1.0
52
52
  Requires-Dist: opentelemetry-exporter-gcp-trace<2.0.0,>=1.6.0
53
53
  Requires-Dist: opentelemetry-exporter-otlp-proto-http<2.0.0,>=1.22.0
54
+ Requires-Dist: platformdirs<5.0.0,>=4.0.0
55
+ Requires-Dist: posthog<8.0.0,>=7.0.0
54
56
  Requires-Dist: psycopg-binary<4.0.0,>=3.3.0
55
57
  Requires-Dist: pydantic<3.0.0,>=2.11.7
56
58
  Requires-Dist: python-dotenv>=1.1.1
59
+ Requires-Dist: pyyaml<7.0.0,>=6.0.0
57
60
  Requires-Dist: sqlalchemy<3.0.0,>=2.0.36
58
61
  Requires-Dist: streamlit<2.0.0,>=1.47.1
59
62
  Requires-Dist: tavily-python<0.8.0,>=0.7.9
63
+ Requires-Dist: textual<7.4.0,>=7.3.0
60
64
  Requires-Dist: uvicorn<0.36.0,>=0.35.0
61
65
  Description-Content-Type: text/markdown
62
66
 
@@ -72,7 +76,7 @@ Idun Agent Engine is a lightweight runtime and SDK that wraps your agent with a
72
76
  pip install idun-agent-engine
73
77
  ```
74
78
 
75
- - Requires Python 3.13
79
+ - Requires Python 3.12+
76
80
  - Ships with FastAPI, Uvicorn, LangGraph, SQLite checkpointing, and optional observability hooks
77
81
 
78
82
  ## Quickstart
@@ -319,9 +323,9 @@ from idun_agent_engine import (
319
323
 
320
324
  Issues and PRs are welcome. See the repository:
321
325
 
322
- - Repo: `https://github.com/geoffreyharrazi/idun-agent-platform`
326
+ - Repo: `https://github.com/Idun-Group/idun-agent-platform`
323
327
  - Package path: `libs/idun_agent_engine`
324
- - Open an issue: `https://github.com/geoffreyharrazi/idun-agent-platform/issues`
328
+ - Open an issue: `https://github.com/Idun-Group/idun-agent-platform/issues`
325
329
 
326
330
  Run locally:
327
331
 
@@ -10,7 +10,7 @@ Idun Agent Engine is a lightweight runtime and SDK that wraps your agent with a
10
10
  pip install idun-agent-engine
11
11
  ```
12
12
 
13
- - Requires Python 3.13
13
+ - Requires Python 3.12+
14
14
  - Ships with FastAPI, Uvicorn, LangGraph, SQLite checkpointing, and optional observability hooks
15
15
 
16
16
  ## Quickstart
@@ -257,9 +257,9 @@ from idun_agent_engine import (
257
257
 
258
258
  Issues and PRs are welcome. See the repository:
259
259
 
260
- - Repo: `https://github.com/geoffreyharrazi/idun-agent-platform`
260
+ - Repo: `https://github.com/Idun-Group/idun-agent-platform`
261
261
  - Package path: `libs/idun_agent_engine`
262
- - Open an issue: `https://github.com/geoffreyharrazi/idun-agent-platform/issues`
262
+ - Open an issue: `https://github.com/Idun-Group/idun-agent-platform/issues`
263
263
 
264
264
  Run locally:
265
265
 
@@ -1,11 +1,11 @@
1
1
  [project]
2
2
  name = "idun-agent-engine"
3
- version = "0.3.9"
3
+ version = "0.4.1"
4
4
  description = "Python SDK and runtime to serve AI agents with FastAPI, LangGraph, and observability."
5
5
  authors = [{ name = "Geoffrey HARRAZI", email = "geoffreyharrazi@gmail.com" }]
6
6
  requires-python = ">=3.12,<3.14"
7
7
  readme = "README.md"
8
- license = "MIT"
8
+ license = "GPL-3.0-only"
9
9
  keywords = [
10
10
  "agents",
11
11
  "langgraph",
@@ -15,7 +15,7 @@ keywords = [
15
15
  "observability",
16
16
  ]
17
17
  classifiers = [
18
- "License :: OSI Approved :: MIT License",
18
+ "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
19
19
  "Programming Language :: Python :: 3",
20
20
  "Programming Language :: Python :: 3 :: Only",
21
21
  "Programming Language :: Python :: 3.12",
@@ -32,7 +32,7 @@ classifiers = [
32
32
  dependencies = [
33
33
  "tavily-python>=0.7.9,<0.8.0",
34
34
  "deepagents>=0.2.8,<1.0.0",
35
- "guardrails-ai>=0.7.0, <0.8.0",
35
+ "guardrails-ai>=0.7.2, <0.8.0",
36
36
  "fastapi>=0.115.0,<0.116.0",
37
37
  "uvicorn>=0.35.0,<0.36.0",
38
38
  "langgraph>=1.0.0,<2.0.0",
@@ -50,6 +50,7 @@ dependencies = [
50
50
  "arize-phoenix-otel>=0.2.0,<1.0.0",
51
51
  "openinference-instrumentation-langchain>=0.1.13,<1.0.0",
52
52
  "langchain>=1.0.0,<2.0.0",
53
+ "textual>=7.3.0,<7.4.0",
53
54
  # Pin <12: 12.x currently depends on placeholder jmespath==99.99.99 and fails in Docker
54
55
  "arize-phoenix>=11.22.0,<12.0.0",
55
56
  "idun-agent-schema>=0.3.8,<1.0.0",
@@ -60,7 +61,7 @@ dependencies = [
60
61
  "sqlalchemy>=2.0.36,<3.0.0",
61
62
  "ag-ui-langgraph>=0.0.20,<0.1.0",
62
63
  "copilotkit>=0.1.72,<0.2.0",
63
- "langchain-mcp-adapters>=0.1.0,<0.2.0",
64
+ "langchain-mcp-adapters>=0.2.0,<0.3.0",
64
65
  "ag-ui-adk>=0.3.4,<0.4.0",
65
66
  "opentelemetry-exporter-gcp-trace>=1.6.0,<2.0.0",
66
67
  "openinference-instrumentation-guardrails>=0.1.0,<1.0.0",
@@ -71,6 +72,9 @@ dependencies = [
71
72
  "opentelemetry-exporter-otlp-proto-http>=1.22.0,<2.0.0",
72
73
  "mcp>=1.0.0,<2.0.0",
73
74
  "psycopg-binary>=3.3.0,<4.0.0",
75
+ "platformdirs>=4.0.0,<5.0.0",
76
+ "posthog>=7.0.0,<8.0.0",
77
+ "PyYAML>=6.0.0,<7.0.0",
74
78
  ]
75
79
 
76
80
 
@@ -104,7 +108,15 @@ include = [
104
108
  ]
105
109
 
106
110
  [tool.hatch.build.targets.wheel]
107
- packages = ["src/idun_agent_engine", "src/idun_platform_cli"]
111
+ include = [
112
+ "src/idun_agent_engine",
113
+ "src/idun_agent_engine/py.typed",
114
+ "src/idun_platform_cli",
115
+ ]
116
+
117
+ [tool.hatch.build.targets.wheel.sources]
118
+ "src/idun_agent_engine" = "idun_agent_engine"
119
+ "src/idun_platform_cli" = "idun_platform_cli"
108
120
 
109
121
  [build-system]
110
122
  requires = ["hatchling"]
@@ -1,3 +1,3 @@
1
1
  """Version information for Idun Agent Engine."""
2
2
 
3
- __version__ = "0.3.9"
3
+ __version__ = "0.4.1"
@@ -123,7 +123,7 @@ class AdkAgent(agent_base.BaseAgent):
123
123
  # Observability (provider-agnostic)
124
124
  if observability_config:
125
125
  handlers, infos = observability.create_observability_handlers(
126
- observability_config # type: ignore[arg-type]
126
+ observability_config # type: ignore[arg-type]
127
127
  )
128
128
  self._obs_callbacks = []
129
129
  for handler in handlers:
@@ -153,6 +153,7 @@ class AdkAgent(agent_base.BaseAgent):
153
153
 
154
154
  if is_langfuse_enabled:
155
155
  import os
156
+
156
157
  langfuse_pk = os.environ.get("LANGFUSE_PUBLIC_KEY")
157
158
  langfuse_host = os.environ.get("LANGFUSE_BASE_URL")
158
159
  print(f"LANGFUSE_PUBLIC_KEY: {langfuse_pk}")
@@ -171,7 +172,9 @@ class AdkAgent(agent_base.BaseAgent):
171
172
  except Exception as e:
172
173
  print(f"Failed to instrument Google ADK: {e}")
173
174
  except Exception as e:
174
- print(f"Error checking observability config for ADK instrumentation: {e}")
175
+ print(
176
+ f"Error checking observability config for ADK instrumentation: {e}"
177
+ )
175
178
 
176
179
  # Initialize Session Service
177
180
  await self._initialize_session_service()
@@ -202,7 +202,7 @@ class LanggraphAgent(agent_base.BaseAgent):
202
202
  self._agent_instance = graph_builder.compile(
203
203
  checkpointer=self._checkpointer, store=self._store
204
204
  )
205
- elif isinstance(graph_builder, CompiledStateGraph):
205
+ elif isinstance(graph_builder, CompiledStateGraph): # TODO: to remove, dirty fix for template deepagent langgraph
206
206
  self._agent_instance = graph_builder
207
207
 
208
208
  self._copilotkit_agent_instance = LangGraphAGUIAgent(
@@ -8,24 +8,24 @@ import os
8
8
  from pathlib import Path
9
9
  from typing import Any
10
10
 
11
- from idun_agent_schema.engine.guardrails import Guardrails as GuardrailsV1
12
11
  import yaml
12
+ from idun_agent_schema.engine.adk import AdkAgentConfig
13
13
  from idun_agent_schema.engine.agent_framework import AgentFramework
14
+ from idun_agent_schema.engine.guardrails_v2 import GuardrailsV2 as Guardrails
14
15
  from idun_agent_schema.engine.haystack import HaystackAgentConfig
15
16
  from idun_agent_schema.engine.langgraph import (
16
17
  LangGraphAgentConfig,
17
18
  SqliteCheckpointConfig,
18
19
  )
19
- from idun_agent_schema.engine.adk import AdkAgentConfig
20
20
  from idun_agent_schema.engine.mcp_server import MCPServer
21
21
  from idun_agent_schema.engine.observability_v2 import ObservabilityConfig
22
- from idun_agent_schema.engine.guardrails_v2 import GuardrailsV2 as Guardrails
23
- from idun_agent_engine.server.server_config import ServerAPIConfig
22
+ from idun_agent_schema.manager.guardrail_configs import convert_guardrail
24
23
  from yaml import YAMLError
25
24
 
25
+ from idun_agent_engine.server.server_config import ServerAPIConfig
26
+
26
27
  from ..agent.base import BaseAgent
27
28
  from .engine_config import AgentConfig, EngineConfig, ServerConfig
28
- from idun_agent_schema.manager.guardrail_configs import convert_guardrail
29
29
 
30
30
 
31
31
  class ConfigBuilder:
@@ -518,6 +518,9 @@ class ConfigBuilder:
518
518
  def load_from_file(config_path: str = "config.yaml") -> EngineConfig:
519
519
  """Load configuration from a YAML file and return a validated EngineConfig.
520
520
 
521
+ Sets IDUN_CONFIG_PATH environment variable to enable MCP helper functions
522
+ (get_adk_tools, get_langchain_tools) to automatically discover the config file.
523
+
521
524
  Args:
522
525
  config_path: Path to the configuration YAML file
523
526
 
@@ -533,6 +536,9 @@ class ConfigBuilder:
533
536
  # Resolve relative to the current working directory
534
537
  path = Path.cwd() / path
535
538
 
539
+ # Set IDUN_CONFIG_PATH for MCP helpers to discover
540
+ os.environ["IDUN_CONFIG_PATH"] = str(path)
541
+
536
542
  with open(path) as f:
537
543
  config_data = yaml.safe_load(f)
538
544
 
@@ -0,0 +1,5 @@
1
+ """Guardrails Hub integration module."""
2
+
3
+ from .guardrails_hub import GuardrailsHubGuard
4
+
5
+ __all__ = ["GuardrailsHubGuard"]
@@ -0,0 +1,21 @@
1
+ """MCP utilities for Idun Agent Engine."""
2
+
3
+ from .registry import MCPClientRegistry
4
+ from .helpers import (
5
+ get_adk_tools_from_api,
6
+ get_adk_tools_from_file,
7
+ get_adk_tools,
8
+ get_langchain_tools,
9
+ get_langchain_tools_from_api,
10
+ get_langchain_tools_from_file,
11
+ )
12
+
13
+ __all__ = [
14
+ "MCPClientRegistry",
15
+ "get_adk_tools_from_api",
16
+ "get_adk_tools_from_file",
17
+ "get_adk_tools",
18
+ "get_langchain_tools",
19
+ "get_langchain_tools_from_api",
20
+ "get_langchain_tools_from_file",
21
+ ]
@@ -0,0 +1,189 @@
1
+ from pathlib import Path
2
+ from typing import Any
3
+ import yaml
4
+ import requests
5
+ import os
6
+ from idun_agent_engine.mcp.registry import MCPClientRegistry
7
+ from idun_agent_schema.engine.mcp_server import MCPServer
8
+
9
+
10
+ def _extract_mcp_configs(config_data: dict[str, Any]) -> list[MCPServer]:
11
+ """Parse MCP server configs from a config dictionary."""
12
+ mcp_configs_data = config_data.get("mcp_servers") or config_data.get("mcpServers")
13
+ if not mcp_configs_data:
14
+ return []
15
+ return [MCPServer.model_validate(c) for c in mcp_configs_data]
16
+
17
+
18
+ def _unwrap_engine_config(config_data: dict[str, Any]) -> dict[str, Any]:
19
+ """Return engine-level config if wrapped under engine_config."""
20
+ if not isinstance(config_data, dict):
21
+ raise ValueError("Configuration payload is empty or invalid")
22
+ if "engine_config" in config_data:
23
+ return config_data["engine_config"]
24
+ return config_data
25
+
26
+
27
+ def _build_registry(config_data: dict[str, Any]) -> MCPClientRegistry | None:
28
+ """Instantiate an MCP client registry from config data."""
29
+ mcp_configs = _extract_mcp_configs(config_data)
30
+ if not mcp_configs:
31
+ return None
32
+ return MCPClientRegistry(mcp_configs)
33
+
34
+
35
+ def _get_toolsets_from_data(config_data: dict[str, Any]) -> list[Any]:
36
+ """Internal helper to extract ADK toolsets from config dictionary."""
37
+ registry = _build_registry(config_data)
38
+ if not registry:
39
+ return []
40
+ try:
41
+ return registry.get_adk_toolsets()
42
+ except ImportError:
43
+ raise
44
+
45
+
46
+ async def _get_langchain_tools_from_data(config_data: dict[str, Any]) -> list[Any]:
47
+ """Internal helper to extract LangChain tools from config dictionary."""
48
+ registry = _build_registry(config_data)
49
+ if not registry:
50
+ return []
51
+ return await registry.get_tools()
52
+
53
+
54
+ def _load_config_from_file(config_path: str | Path) -> dict[str, Any]:
55
+ """Load YAML config (optionally wrapped in engine_config) from disk."""
56
+ path = Path(config_path)
57
+ if not path.exists():
58
+ raise FileNotFoundError(f"Configuration file not found at {path}")
59
+
60
+ with open(path) as f:
61
+ config_data = yaml.safe_load(f)
62
+
63
+ return _unwrap_engine_config(config_data)
64
+
65
+
66
+ def _fetch_config_from_api() -> dict[str, Any]:
67
+ """Fetch configuration from the Idun Manager API."""
68
+ api_key = os.environ.get("IDUN_AGENT_API_KEY")
69
+ manager_host = os.environ.get("IDUN_MANAGER_HOST")
70
+
71
+ if not api_key:
72
+ raise ValueError("Environment variable 'IDUN_AGENT_API_KEY' is not set")
73
+
74
+ if not manager_host:
75
+ raise ValueError("Environment variable 'IDUN_MANAGER_HOST' is not set")
76
+
77
+ headers = {"auth": f"Bearer {api_key}"}
78
+ url = f"{manager_host.rstrip('/')}/api/v1/agents/config"
79
+
80
+ try:
81
+ response = requests.get(url=url, headers=headers)
82
+ response.raise_for_status()
83
+ config_data = yaml.safe_load(response.text)
84
+ return _unwrap_engine_config(config_data)
85
+ except requests.RequestException as e:
86
+ raise ValueError(f"Failed to fetch config from API: {e}") from e
87
+ except yaml.YAMLError as e:
88
+ raise ValueError(f"Failed to parse config YAML: {e}") from e
89
+
90
+
91
+ def get_adk_tools_from_file(config_path: str | Path) -> list[Any]:
92
+ """
93
+ Loads MCP configurations from a YAML file and returns a list of ADK toolsets.
94
+
95
+ Args:
96
+ config_path: Path to the configuration YAML file.
97
+
98
+ Returns:
99
+ List of initialized ADK McpToolset instances.
100
+ """
101
+ config_data = _load_config_from_file(config_path)
102
+ return _get_toolsets_from_data(config_data)
103
+
104
+
105
+ def get_adk_tools_from_api() -> list[Any]:
106
+ """
107
+ Fetches configuration from the Idun Manager API and returns a list of ADK toolsets.
108
+
109
+ Returns:
110
+ List of initialized ADK McpToolset instances.
111
+ """
112
+ config_data = _fetch_config_from_api()
113
+ return _get_toolsets_from_data(config_data)
114
+
115
+
116
+ def get_adk_tools(config_path: str | Path | None = None) -> list[Any]:
117
+ """
118
+ Returns ADK toolsets using config from file when provided, from IDUN_CONFIG_PATH env var, or from API.
119
+
120
+ The function resolves configuration in the following order:
121
+ 1. Uses the provided config_path if specified
122
+ 2. Uses IDUN_CONFIG_PATH environment variable if set
123
+ 3. Falls back to fetching from Idun Manager API
124
+
125
+ Args:
126
+ config_path: Optional path to configuration YAML file. If provided, takes precedence.
127
+
128
+ Returns:
129
+ List of initialized ADK McpToolset instances.
130
+
131
+ Raises:
132
+ ValueError: If no config source is available or API credentials are missing.
133
+ FileNotFoundError: If specified config file doesn't exist.
134
+ """
135
+ if config_path:
136
+ return get_adk_tools_from_file(config_path)
137
+
138
+ # Check for IDUN_CONFIG_PATH environment variable
139
+ env_config_path = os.environ.get("IDUN_CONFIG_PATH")
140
+ if env_config_path:
141
+ return get_adk_tools_from_file(env_config_path)
142
+
143
+ return get_adk_tools_from_api()
144
+
145
+
146
+ async def get_langchain_tools_from_file(config_path: str | Path) -> list[Any]:
147
+ """
148
+ Loads MCP configurations from a YAML file and returns LangChain tool instances.
149
+ """
150
+ config_data = _load_config_from_file(config_path)
151
+ return await _get_langchain_tools_from_data(config_data)
152
+
153
+
154
+ async def get_langchain_tools_from_api() -> list[Any]:
155
+ """
156
+ Fetches configuration from the Idun Manager API and returns LangChain tool instances.
157
+ """
158
+ config_data = _fetch_config_from_api()
159
+ return await _get_langchain_tools_from_data(config_data)
160
+
161
+
162
+ async def get_langchain_tools(config_path: str | Path | None = None) -> list[Any]:
163
+ """
164
+ Returns LangChain tool instances using config from file when provided, from IDUN_CONFIG_PATH env var, or from API.
165
+
166
+ The function resolves configuration in the following order:
167
+ 1. Uses the provided config_path if specified
168
+ 2. Uses IDUN_CONFIG_PATH environment variable if set
169
+ 3. Falls back to fetching from Idun Manager API
170
+
171
+ Args:
172
+ config_path: Optional path to configuration YAML file. If provided, takes precedence.
173
+
174
+ Returns:
175
+ List of initialized LangChain tool instances.
176
+
177
+ Raises:
178
+ ValueError: If no config source is available or API credentials are missing.
179
+ FileNotFoundError: If specified config file doesn't exist.
180
+ """
181
+ if config_path:
182
+ return await get_langchain_tools_from_file(config_path)
183
+
184
+ # Check for IDUN_CONFIG_PATH environment variable
185
+ env_config_path = os.environ.get("IDUN_CONFIG_PATH")
186
+ if env_config_path:
187
+ return await get_langchain_tools_from_file(env_config_path)
188
+
189
+ return await get_langchain_tools_from_api()
@@ -79,7 +79,13 @@ class MCPClientRegistry:
79
79
  raise RuntimeError("MCP client registry is not enabled.")
80
80
  return await self._client.get_tools(server_name=name)
81
81
 
82
- def get_adk_toolsets(self) -> list["McpToolset"]:
82
+ async def get_langchain_tools(self, name: str | None = None) -> list[Any]:
83
+ """
84
+ Alias for get_tools to make intent explicit when using LangChain/LangGraph agents.
85
+ """
86
+ return await self.get_tools(name=name)
87
+
88
+ def get_adk_toolsets(self) -> list[Any]:
83
89
  """Return a list of Google ADK McpToolset instances for configured servers."""
84
90
  if McpToolset is None or StdioServerParameters is None:
85
91
  raise ImportError("google-adk and mcp packages are required for ADK toolsets.")
@@ -15,6 +15,7 @@ from ..mcp import MCPClientRegistry
15
15
  from idun_agent_schema.engine.guardrails import Guardrails, Guardrail
16
16
 
17
17
  from ..guardrails.base import BaseGuardrail
18
+ from ..telemetry import get_telemetry, sanitize_telemetry_config
18
19
 
19
20
 
20
21
  def _parse_guardrails(guardrails_obj: Guardrails) -> Sequence[BaseGuardrail]:
@@ -98,9 +99,30 @@ async def lifespan(app: FastAPI):
98
99
 
99
100
  await configure_app(app, app.state.engine_config)
100
101
 
102
+ try:
103
+ telemetry = get_telemetry()
104
+ app.state.telemetry = telemetry
105
+ agent = getattr(app.state, "agent", None)
106
+ telemetry.capture(
107
+ "engine started",
108
+ properties={
109
+ "agent_type": type(agent).__name__ if agent is not None else None,
110
+ "has_agent": agent is not None,
111
+ "engine_config": sanitize_telemetry_config(app.state.engine_config),
112
+ },
113
+ )
114
+ except Exception as e:
115
+ print(f"⚠️ Warning: Failed to start telemetry: {e}")
116
+ app.state.telemetry = None
117
+
101
118
  yield
102
119
 
103
120
  # Clean up on shutdown
104
121
  print("🔄 Idun Agent Engine shutting down...")
122
+ telemetry = getattr(app.state, "telemetry", None)
123
+ if telemetry is not None:
124
+ telemetry.capture("engine stopped")
105
125
  await cleanup_agent(app)
126
+ if telemetry is not None:
127
+ telemetry.shutdown()
106
128
  print("✅ Agent resources cleaned up successfully.")
@@ -0,0 +1,19 @@
1
+ """Telemetry package for Idun Agent Engine."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from .telemetry import IdunTelemetry, sanitize_telemetry_config
6
+
7
+ _telemetry_singleton: IdunTelemetry | None = None
8
+
9
+
10
+ def get_telemetry() -> IdunTelemetry:
11
+ """Return the process-wide telemetry singleton."""
12
+
13
+ global _telemetry_singleton
14
+ if _telemetry_singleton is None:
15
+ _telemetry_singleton = IdunTelemetry()
16
+ return _telemetry_singleton
17
+
18
+
19
+ __all__ = ["IdunTelemetry", "get_telemetry", "sanitize_telemetry_config"]
@@ -0,0 +1,29 @@
1
+ """Telemetry configuration utilities."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+
7
+ IDUN_TELEMETRY_ENABLED_ENV = "IDUN_TELEMETRY_ENABLED"
8
+
9
+
10
+ def telemetry_enabled(environ: dict[str, str] | None = None) -> bool:
11
+ """Return whether telemetry is enabled.
12
+
13
+ Telemetry is ON by default. Users can disable it by setting the environment
14
+ variable `IDUN_TELEMETRY_ENABLED` to a falsy value (e.g. "false", "0", "no").
15
+ """
16
+
17
+ env = os.environ if environ is None else environ
18
+ raw = env.get(IDUN_TELEMETRY_ENABLED_ENV)
19
+ if raw is None:
20
+ return True
21
+
22
+ value = raw.strip().lower()
23
+ if value in {"0", "false", "no", "off", "disable", "disabled"}:
24
+ return False
25
+ if value in {"1", "true", "yes", "on", "enable", "enabled"}:
26
+ return True
27
+
28
+ # Unknown values default to enabled (opt-out).
29
+ return True