idun-agent-engine 0.4.0__tar.gz → 0.4.2__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 (90) hide show
  1. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/.gitignore +17 -25
  2. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/PKG-INFO +2 -2
  3. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/pyproject.toml +46 -11
  4. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/_version.py +1 -1
  5. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/agent/adk/adk.py +7 -4
  6. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/agent/haystack/__init__.py +0 -2
  7. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/agent/haystack/haystack.py +9 -5
  8. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/agent/langgraph/langgraph.py +10 -13
  9. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/core/config_builder.py +33 -13
  10. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/guardrails/guardrails_hub/guardrails_hub.py +52 -9
  11. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/mcp/helpers.py +53 -15
  12. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/mcp/registry.py +5 -5
  13. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/observability/base.py +11 -2
  14. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/observability/gcp_trace/gcp_trace_handler.py +3 -1
  15. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/observability/langfuse/langfuse_handler.py +1 -3
  16. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/server/dependencies.py +7 -2
  17. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/server/lifespan.py +2 -7
  18. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/server/routers/agent.py +2 -1
  19. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/server/routers/base.py +7 -5
  20. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/telemetry/__init__.py +0 -1
  21. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/telemetry/config.py +0 -1
  22. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/telemetry/telemetry.py +3 -4
  23. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/templates/correction.py +4 -7
  24. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/templates/deep_research.py +1 -0
  25. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/templates/translation.py +4 -4
  26. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/groups/agent/package.py +4 -1
  27. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/groups/agent/serve.py +2 -0
  28. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/groups/init.py +2 -0
  29. idun_agent_engine-0.4.2/src/idun_platform_cli/telemetry.py +55 -0
  30. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/tui/css/create_agent.py +137 -14
  31. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/tui/css/main.py +7 -10
  32. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/tui/main.py +3 -3
  33. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/tui/schemas/create_agent.py +8 -4
  34. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/tui/screens/create_agent.py +186 -20
  35. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/tui/utils/config.py +23 -2
  36. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/tui/validators/guardrails.py +20 -6
  37. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/tui/validators/mcps.py +9 -6
  38. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/tui/widgets/__init__.py +8 -4
  39. idun_agent_engine-0.4.2/src/idun_platform_cli/tui/widgets/chat_widget.py +155 -0
  40. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/tui/widgets/guardrails_widget.py +12 -4
  41. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/tui/widgets/identity_widget.py +28 -10
  42. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/tui/widgets/mcps_widget.py +113 -25
  43. idun_agent_engine-0.4.2/src/idun_platform_cli/tui/widgets/memory_widget.py +194 -0
  44. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/tui/widgets/observability_widget.py +12 -14
  45. idun_agent_engine-0.4.2/src/idun_platform_cli/tui/widgets/serve_widget.py +81 -0
  46. idun_agent_engine-0.4.0/src/idun_agent_engine/agent/haystack/haystack_model.py +0 -13
  47. idun_agent_engine-0.4.0/src/idun_agent_engine/guardrails/guardrails_hub/utils.py +0 -1
  48. idun_agent_engine-0.4.0/src/idun_agent_engine/server/routers/agui.py +0 -47
  49. idun_agent_engine-0.4.0/src/idun_platform_cli/tui/widgets/serve_widget.py +0 -78
  50. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/README.md +0 -0
  51. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/__init__.py +0 -0
  52. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/agent/__init__.py +0 -0
  53. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/agent/adk/__init__.py +0 -0
  54. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/agent/base.py +0 -0
  55. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/agent/haystack/utils.py +0 -0
  56. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/agent/langgraph/__init__.py +0 -0
  57. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/core/__init__.py +0 -0
  58. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/core/app_factory.py +0 -0
  59. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/core/engine_config.py +0 -0
  60. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/core/server_runner.py +0 -0
  61. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/guardrails/__init__.py +0 -0
  62. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/guardrails/base.py +0 -0
  63. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/guardrails/guardrails_hub/__init__.py +0 -0
  64. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/mcp/__init__.py +2 -2
  65. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/observability/__init__.py +0 -0
  66. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/observability/gcp_logging/__init__.py +0 -0
  67. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/observability/gcp_logging/gcp_logging_handler.py +0 -0
  68. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/observability/gcp_trace/__init__.py +0 -0
  69. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/observability/langfuse/__init__.py +0 -0
  70. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/observability/phoenix/__init__.py +0 -0
  71. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/observability/phoenix/phoenix_handler.py +0 -0
  72. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/observability/phoenix_local/__init__.py +0 -0
  73. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/observability/phoenix_local/phoenix_local_handler.py +0 -0
  74. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/py.typed +0 -0
  75. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/server/__init__.py +0 -0
  76. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/server/routers/__init__.py +0 -0
  77. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/server/server_config.py +0 -0
  78. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_agent_engine/templates/__init__.py +0 -0
  79. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/__init__.py +0 -0
  80. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/groups/__init__.py +0 -0
  81. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/groups/agent/__init__.py +0 -0
  82. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/groups/agent/main.py +0 -0
  83. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/main.py +0 -0
  84. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/tui/__init__.py +0 -0
  85. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/tui/css/__init__.py +0 -0
  86. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/tui/schemas/__init__.py +0 -0
  87. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/tui/screens/__init__.py +0 -0
  88. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/tui/utils/__init__.py +0 -0
  89. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/tui/validators/__init__.py +0 -0
  90. {idun_agent_engine-0.4.0 → idun_agent_engine-0.4.2}/src/idun_platform_cli/tui/validators/observability.py +0 -0
@@ -3,6 +3,8 @@ __pycache__/
3
3
  *.py[cod]
4
4
  *$py.class
5
5
 
6
+
7
+
6
8
  .python-version
7
9
  # C extensions
8
10
  *.so
@@ -128,15 +130,24 @@ celerybeat.pid
128
130
  # SageMath parsed files
129
131
  *.sage.py
130
132
 
131
- # Environments
133
+ # Environments / local config
132
134
  .env
133
- .venv
135
+ .env.*
136
+ !.env.example
137
+ .venv/
134
138
  env/
135
139
  venv/
136
140
  ENV/
137
141
  env.bak/
138
142
  venv.bak/
139
143
 
144
+ # Node / frontend
145
+ node_modules/
146
+ npm-debug.log*
147
+ yarn-debug.log*
148
+ yarn-error.log*
149
+ pnpm-debug.log*
150
+
140
151
  # Spyder project settings
141
152
  .spyderproject
142
153
  .spyproject
@@ -177,34 +188,15 @@ cython_debug/
177
188
  # Database files
178
189
  *.db
179
190
  *.db-shm
180
- *.db-wai
191
+ *.db-wal
181
192
  *.db-journal*
182
193
  *.sqlite
183
194
  *.sqlite3
184
195
  agents.db
185
196
  checkpoint_async.db
186
197
 
187
- # Python virtual environment
188
- .venv/
189
- venv/
190
- ENV/
191
-
192
- # Python cache
193
- __pycache__/
194
- *.pyc
195
- *.pyo
196
- *.pyd
197
-
198
- # Poetry
198
+ # Poetry (unused in this repo)
199
199
  poetry.lock
200
200
 
201
- # Environment variables
202
- .env
203
-
204
- # Custom Gitignore for Idun
205
- *.db-wal
206
- .DS_Store
207
- *.DS_Store
208
-
209
- # uv lock file
210
- uv.lock
201
+ # Editor / tool artifacts
202
+ .specstory/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: idun-agent-engine
3
- Version: 0.4.0
3
+ Version: 0.4.2
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
@@ -31,7 +31,7 @@ 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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "idun-agent-engine"
3
- version = "0.4.0"
3
+ version = "0.4.2"
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"
@@ -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,7 +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
+ "textual>=7.3.0,<7.4.0",
54
54
  # Pin <12: 12.x currently depends on placeholder jmespath==99.99.99 and fails in Docker
55
55
  "arize-phoenix>=11.22.0,<12.0.0",
56
56
  "idun-agent-schema>=0.3.8,<1.0.0",
@@ -98,6 +98,8 @@ dev = [
98
98
  "pytest-cov>=5.0.0,<7",
99
99
  "types-PyYAML>=6.0.12.20240808,<7",
100
100
  "pytest-asyncio>=1.2.0",
101
+ "pytest-xdist>=3.8.0",
102
+ "posthog>=7.5.1",
101
103
  ]
102
104
 
103
105
  [tool.hatch.build.targets.sdist]
@@ -155,10 +157,16 @@ select = [
155
157
  "UP", # pyupgrade
156
158
  "N", # pep8-naming
157
159
  "SIM", # flake8-simplify
158
- "D", # pydocstyle (docstrings)
159
160
  ]
160
161
  extend-ignore = [
161
162
  "E501", # line length handled by black
163
+ # Keep linting actionable without behavior changes across the codebase.
164
+ "E722", # bare except
165
+ "B904", # raise from within except
166
+ "SIM105", # prefer contextlib.suppress
167
+ "SIM117", # combine nested with
168
+ "SIM118", # key in dict instead of key in dict.keys()
169
+ "UP038", # isinstance union style
162
170
  ]
163
171
 
164
172
  [tool.ruff.lint.per-file-ignores]
@@ -180,18 +188,45 @@ pretty = true
180
188
  show_error_codes = true
181
189
 
182
190
  [tool.pytest.ini_options]
183
- addopts = "-ra -q --strict-markers --disable-warnings"
184
- testpaths = [
185
- "tests",
191
+ asyncio_mode = "auto"
192
+ asyncio_default_fixture_loop_scope = "function"
193
+ addopts = "-ra -q --strict-markers"
194
+ testpaths = ["tests/unit", "tests/integration"]
195
+ pythonpath = ["src", "tests"]
196
+ filterwarnings = [
197
+ "ignore::DeprecationWarning",
198
+ "ignore::PendingDeprecationWarning",
186
199
  ]
187
- pythonpath = [
188
- "src",
200
+ markers = [
201
+ "unit: Unit tests (fast, no external dependencies)",
202
+ "integration: Integration tests (may require external services)",
203
+ "slow: Slow tests (marked for optional skipping)",
204
+ "requires_langfuse: Test requires Langfuse service",
205
+ "requires_phoenix: Test requires Phoenix service",
206
+ "requires_postgres: Test requires PostgreSQL",
189
207
  ]
190
208
 
191
209
  [tool.coverage.run]
192
210
  branch = true
193
- source = ["src"]
211
+ source = ["src/idun_agent_engine"]
212
+ omit = [
213
+ "*/__init__.py",
214
+ "*/templates/*",
215
+ "*/_version.py",
216
+ "*/idun_agent_engine_ui/*",
217
+ "*/idun_platform_cli/*",
218
+ "*/mcp/*", # CHANGED: MCP has Pydantic compatibility issues with coverage
219
+ ]
194
220
 
195
221
  [tool.coverage.report]
196
222
  show_missing = true
197
- skip_covered = true
223
+ skip_covered = false
224
+ fail_under = 0 # Start with 0, increase as coverage grows
225
+ exclude_lines = [
226
+ "pragma: no cover",
227
+ "if TYPE_CHECKING:",
228
+ "raise NotImplementedError",
229
+ "if __name__ == .__main__.:",
230
+ "@abstractmethod",
231
+ "pass",
232
+ ]
@@ -1,3 +1,3 @@
1
1
  """Version information for Idun Agent Engine."""
2
2
 
3
- __version__ = "0.4.0"
3
+ __version__ = "0.4.2"
@@ -5,6 +5,7 @@ import uuid
5
5
  from collections.abc import AsyncGenerator
6
6
  from typing import Any
7
7
 
8
+ from ag_ui_adk import ADKAgent as ADKAGUIAgent
8
9
  from google.adk.apps.app import App
9
10
  from google.adk.memory import (
10
11
  InMemoryMemoryService,
@@ -25,9 +26,8 @@ from idun_agent_schema.engine.adk import (
25
26
  )
26
27
  from idun_agent_schema.engine.observability_v2 import ObservabilityConfig
27
28
 
28
- from ag_ui_adk import ADKAgent as ADKAGUIAgent
29
- from idun_agent_engine.agent import base as agent_base
30
29
  from idun_agent_engine import observability
30
+ from idun_agent_engine.agent import base as agent_base
31
31
 
32
32
 
33
33
  class AdkAgent(agent_base.BaseAgent):
@@ -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()
@@ -1,9 +1,7 @@
1
1
  """LangGraph agent package."""
2
2
 
3
3
  from .haystack import HaystackAgent
4
- from .haystack_model import HaystackAgentConfig
5
4
 
6
5
  __all__ = [
7
6
  "HaystackAgent",
8
- "HaystackAgentConfig",
9
7
  ]
@@ -10,9 +10,10 @@ from haystack import Pipeline
10
10
  from haystack.components.agents import Agent
11
11
  from haystack.dataclasses import ChatMessage
12
12
  from haystack_integrations.components.connectors.langfuse import LangfuseConnector
13
+ from idun_agent_schema.engine.haystack import HaystackAgentConfig
14
+ from idun_agent_schema.engine.observability_v2 import ObservabilityConfig
13
15
 
14
16
  from idun_agent_engine.agent.base import BaseAgent
15
- from idun_agent_schema.engine.haystack import HaystackAgentConfig
16
17
  from idun_agent_engine.agent.haystack.utils import _parse_component_definition
17
18
 
18
19
  logging.basicConfig(
@@ -77,7 +78,9 @@ class HaystackAgent(BaseAgent):
77
78
  Raises:
78
79
  RuntimeError: If the CopilotKit agent is not yet initialized.
79
80
  """
80
- raise NotImplementedError("CopilotKit agent instance not supported yet for Haystack agent.")
81
+ raise NotImplementedError(
82
+ "CopilotKit agent instance not supported yet for Haystack agent."
83
+ )
81
84
 
82
85
  @property
83
86
  def configuration(self) -> HaystackAgentConfig:
@@ -146,9 +149,10 @@ class HaystackAgent(BaseAgent):
146
149
  # TODO: await persistence haystack
147
150
  # TODO OBS block
148
151
 
149
- # check if config has observability `enabled` or `disabled`, so that we adjust our component to
150
- # either add a tracer or not
151
- if self._configuration.observability.enabled:
152
+ if (
153
+ self._configuration.observability
154
+ and self._configuration.observability.enabled
155
+ ): # FIXED: should also check for enabled
152
156
  self._enable_tracing = True
153
157
  logger.info("Enabling tracing...")
154
158
  component: Agent | Pipeline = self._load_component(
@@ -1,7 +1,7 @@
1
1
  """LangGraph agent adapter implementing the BaseAgent protocol."""
2
2
 
3
- import importlib.util
4
3
  import importlib
4
+ import importlib.util
5
5
  import uuid
6
6
  from collections.abc import AsyncGenerator
7
7
  from typing import Any
@@ -9,6 +9,7 @@ from typing import Any
9
9
  import aiosqlite
10
10
  from ag_ui.core import events as ag_events
11
11
  from ag_ui.core import types as ag_types
12
+ from copilotkit import LangGraphAGUIAgent
12
13
  from idun_agent_schema.engine.langgraph import (
13
14
  InMemoryCheckpointConfig,
14
15
  LangGraphAgentConfig,
@@ -24,7 +25,6 @@ from langgraph.graph.state import CompiledStateGraph
24
25
 
25
26
  from idun_agent_engine import observability
26
27
  from idun_agent_engine.agent import base as agent_base
27
- from copilotkit import LangGraphAGUIAgent
28
28
 
29
29
 
30
30
  class LanggraphAgent(agent_base.BaseAgent):
@@ -202,8 +202,11 @@ 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): # TODO: to remove, dirty fix for template deepagent langgraph
206
- self._agent_instance = graph_builder
205
+ elif isinstance(graph_builder, CompiledStateGraph):
206
+ # TODO: this was made for supporting langgraph's DeepAgent, modernize.
207
+ raise TypeError(
208
+ "Expected StateGraph, Got CompiledStateGraph. Make sure not to run `compile` on your agent's graph."
209
+ )
207
210
 
208
211
  self._copilotkit_agent_instance = LangGraphAGUIAgent(
209
212
  name=self._name,
@@ -212,12 +215,6 @@ class LanggraphAgent(agent_base.BaseAgent):
212
215
  config={"callbacks": self._obs_callbacks} if self._obs_callbacks else None,
213
216
  )
214
217
 
215
- self._copilotkit_agent_instance = LangGraphAGUIAgent(
216
- name=self._name,
217
- description="Agent description", # TODO: add agent description
218
- graph=self._agent_instance,
219
- )
220
-
221
218
  if self._agent_instance:
222
219
  try:
223
220
  self._input_schema = self._agent_instance.input_schema
@@ -252,9 +249,10 @@ class LanggraphAgent(agent_base.BaseAgent):
252
249
 
253
250
  if self._configuration.checkpointer:
254
251
  if isinstance(self._configuration.checkpointer, SqliteCheckpointConfig):
255
- self._connection = await aiosqlite.connect(
256
- self._configuration.checkpointer.db_path
252
+ db_path = self._configuration.checkpointer.db_url.replace(
253
+ "sqlite:///", ""
257
254
  )
255
+ self._connection = await aiosqlite.connect(db_path)
258
256
  self._checkpointer = AsyncSqliteSaver(conn=self._connection)
259
257
  self._infos["checkpointer"] = (
260
258
  self._configuration.checkpointer.model_dump()
@@ -344,7 +342,6 @@ class LanggraphAgent(agent_base.BaseAgent):
344
342
  def _validate_graph_builder(
345
343
  self, graph_builder: Any, module_path: str, graph_variable_name: str
346
344
  ) -> StateGraph:
347
- # TODO to remove, dirty fix for template deepagent langgraph
348
345
  if not isinstance(graph_builder, StateGraph) and not isinstance(
349
346
  graph_builder, CompiledStateGraph
350
347
  ):
@@ -4,6 +4,7 @@ This module provides a fluent API for building configuration objects using Pydan
4
4
  This approach ensures type safety, validation, and consistency with the rest of the codebase.
5
5
  """
6
6
 
7
+ import os
7
8
  from pathlib import Path
8
9
  from typing import Any
9
10
 
@@ -50,7 +51,6 @@ class ConfigBuilder:
50
51
  """Initialize a new configuration builder with default values."""
51
52
  self._server_config = ServerConfig()
52
53
  self._agent_config: AgentConfig | None = None
53
- # TODO: add mcp_servers config
54
54
  self._mcp_servers: list[MCPServer] | None = None
55
55
  self._observability: list[ObservabilityConfig] | None = None
56
56
  self._guardrails: Guardrails | None = None
@@ -259,7 +259,7 @@ class ConfigBuilder:
259
259
  mcp_servers=self._mcp_servers,
260
260
  )
261
261
 
262
- def build_dict(self) -> dict[str, Any]:
262
+ def build_dict(self) -> dict[str, Any]: # NOT USED
263
263
  """Build and return the configuration as a dictionary.
264
264
 
265
265
  This is a convenience method for backward compatibility.
@@ -268,17 +268,24 @@ class ConfigBuilder:
268
268
  Dict[str, Any]: The complete configuration dictionary
269
269
  """
270
270
  engine_config = self.build()
271
- return engine_config.model_dump()
271
+ return engine_config.model_dump(mode="python")
272
272
 
273
- def save_to_file(self, file_path: str) -> None:
273
+ def save_to_file(
274
+ self, file_path: str
275
+ ) -> None: # FIXED: old method doesn't serialize enums correctly
274
276
  """Save the configuration to a YAML file.
275
277
 
276
278
  Args:
277
279
  file_path: Path where to save the configuration file
278
280
  """
279
- config = self.build_dict()
281
+ engine_model = self.build()
280
282
  with open(file_path, "w") as f:
281
- yaml.dump(config, f, default_flow_style=False, indent=2)
283
+ yaml.dump(
284
+ engine_model.model_dump(mode="json"),
285
+ f,
286
+ default_flow_style=False,
287
+ indent=2,
288
+ )
282
289
 
283
290
  async def build_and_initialize_agent(
284
291
  self, mcp_registry: Any | None = None
@@ -319,9 +326,10 @@ class ConfigBuilder:
319
326
  # Initialize the appropriate agent
320
327
  agent_instance = None
321
328
  if agent_type == AgentFramework.LANGGRAPH:
322
- from idun_agent_engine.agent.langgraph.langgraph import LanggraphAgent
323
329
  import os
324
330
 
331
+ from idun_agent_engine.agent.langgraph.langgraph import LanggraphAgent
332
+
325
333
  print("Current directory: ", os.getcwd()) # TODO remove
326
334
  try:
327
335
  validated_config = LangGraphAgentConfig.model_validate(agent_config_obj)
@@ -334,10 +342,12 @@ class ConfigBuilder:
334
342
  agent_instance = LanggraphAgent()
335
343
 
336
344
  elif agent_type == AgentFramework.TRANSLATION_AGENT:
337
- from idun_agent_engine.agent.langgraph.langgraph import LanggraphAgent
338
- from idun_agent_schema.engine.templates import TranslationAgentConfig
339
345
  import os
340
346
 
347
+ from idun_agent_schema.engine.templates import TranslationAgentConfig
348
+
349
+ from idun_agent_engine.agent.langgraph.langgraph import LanggraphAgent
350
+
341
351
  try:
342
352
  translation_config = TranslationAgentConfig.model_validate(
343
353
  agent_config_obj
@@ -364,10 +374,12 @@ class ConfigBuilder:
364
374
  agent_instance = LanggraphAgent()
365
375
 
366
376
  elif agent_type == AgentFramework.CORRECTION_AGENT:
367
- from idun_agent_engine.agent.langgraph.langgraph import LanggraphAgent
368
- from idun_agent_schema.engine.templates import CorrectionAgentConfig
369
377
  import os
370
378
 
379
+ from idun_agent_schema.engine.templates import CorrectionAgentConfig
380
+
381
+ from idun_agent_engine.agent.langgraph.langgraph import LanggraphAgent
382
+
371
383
  try:
372
384
  correction_config = CorrectionAgentConfig.model_validate(
373
385
  agent_config_obj
@@ -391,10 +403,12 @@ class ConfigBuilder:
391
403
  agent_instance = LanggraphAgent()
392
404
 
393
405
  elif agent_type == AgentFramework.DEEP_RESEARCH_AGENT:
394
- from idun_agent_engine.agent.langgraph.langgraph import LanggraphAgent
395
- from idun_agent_schema.engine.templates import DeepResearchAgentConfig
396
406
  import os
397
407
 
408
+ from idun_agent_schema.engine.templates import DeepResearchAgentConfig
409
+
410
+ from idun_agent_engine.agent.langgraph.langgraph import LanggraphAgent
411
+
398
412
  try:
399
413
  deep_research_config = DeepResearchAgentConfig.model_validate(
400
414
  agent_config_obj
@@ -517,6 +531,9 @@ class ConfigBuilder:
517
531
  def load_from_file(config_path: str = "config.yaml") -> EngineConfig:
518
532
  """Load configuration from a YAML file and return a validated EngineConfig.
519
533
 
534
+ Sets IDUN_CONFIG_PATH environment variable to enable MCP helper functions
535
+ (get_adk_tools, get_langchain_tools) to automatically discover the config file.
536
+
520
537
  Args:
521
538
  config_path: Path to the configuration YAML file
522
539
 
@@ -532,6 +549,9 @@ class ConfigBuilder:
532
549
  # Resolve relative to the current working directory
533
550
  path = Path.cwd() / path
534
551
 
552
+ # Set IDUN_CONFIG_PATH for MCP helpers to discover
553
+ os.environ["IDUN_CONFIG_PATH"] = str(path)
554
+
535
555
  with open(path) as f:
536
556
  config_data = yaml.safe_load(f)
537
557
 
@@ -9,26 +9,51 @@ from ..base import BaseGuardrail
9
9
 
10
10
  def get_guard_instance(name: GuardrailConfigId) -> Guard:
11
11
  """Returns a map of guard type -> guard instance."""
12
- if name.value == "ban_list":
12
+ if name == GuardrailConfigId.BAN_LIST:
13
13
  from guardrails.hub import BanList
14
14
 
15
15
  return BanList
16
16
 
17
- elif name.value == "detect_pii":
17
+ elif name == GuardrailConfigId.DETECT_PII:
18
18
  from guardrails.hub import DetectPII
19
19
 
20
20
  return DetectPII
21
21
 
22
- elif name.value == "nsfw":
22
+ elif name == GuardrailConfigId.NSFW_TEXT:
23
23
  from guardrails.hub import NSFWText
24
24
 
25
25
  return NSFWText
26
26
 
27
- elif name.value == "competitor_check":
27
+ elif name == GuardrailConfigId.COMPETITION_CHECK:
28
28
  from guardrails.hub import CompetitorCheck
29
29
 
30
30
  return CompetitorCheck
31
31
 
32
+ elif name == GuardrailConfigId.BIAS_CHECK:
33
+ from guardrails.hub import BiasCheck
34
+
35
+ return BiasCheck
36
+
37
+ elif name == GuardrailConfigId.CORRECT_LANGUAGE:
38
+ from guardrails.hub import ValidLanguage
39
+
40
+ return ValidLanguage
41
+
42
+ elif name == GuardrailConfigId.GIBBERISH_TEXT:
43
+ from guardrails.hub import GibberishText
44
+
45
+ return GibberishText
46
+
47
+ elif name == GuardrailConfigId.TOXIC_LANGUAGE:
48
+ from guardrails.hub import ToxicLanguage
49
+
50
+ return ToxicLanguage
51
+
52
+ elif name == GuardrailConfigId.RESTRICT_TO_TOPIC:
53
+ from guardrails.hub import RestrictToTopic
54
+
55
+ return RestrictToTopic
56
+
32
57
  else:
33
58
  raise ValueError(f"Guard {name} not found.")
34
59
 
@@ -90,11 +115,29 @@ class GuardrailsHubGuard(BaseGuardrail):
90
115
  f"Guard: {self.guard_id} is not yet supported, or does not exist."
91
116
  )
92
117
 
93
- guard_instance_params = self._guardrail_config.guard_params.model_dump()
94
- guard_instance = guard(**guard_instance_params)
95
- for param, value in guard_instance_params.items():
96
- setattr(guard_instance, param, value)
97
- return guard_instance
118
+ if hasattr(self._guardrail_config, "guard_params"):
119
+ guard_instance_params = self._guardrail_config.guard_params.model_dump()
120
+ else:
121
+ config_dict = self._guardrail_config.model_dump()
122
+ exclude_fields = {"config_id", "api_key", "reject_message", "guard_url"}
123
+ guard_instance_params = {
124
+ k: v for k, v in config_dict.items() if k not in exclude_fields
125
+ }
126
+
127
+ try:
128
+ guard_instance = guard(**guard_instance_params)
129
+ for param, value in guard_instance_params.items():
130
+ setattr(guard_instance, param, value)
131
+ return guard_instance
132
+ except SystemError:
133
+ # sentencepiece mutex lock error when loading models in quick succession
134
+ import time
135
+
136
+ time.sleep(0.5)
137
+ guard_instance = guard(**guard_instance_params)
138
+ for param, value in guard_instance_params.items():
139
+ setattr(guard_instance, param, value)
140
+ return guard_instance
98
141
 
99
142
  def validate(self, input: str) -> bool:
100
143
  """TODO."""