idun-agent-engine 0.3.0__py3-none-any.whl → 0.3.2__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.
@@ -1,3 +1,3 @@
1
1
  """Version information for Idun Agent Engine."""
2
2
 
3
- __version__ = "0.3.0"
3
+ __version__ = "0.3.2"
@@ -96,7 +96,9 @@ class LanggraphAgent(agent_base.BaseAgent):
96
96
  RuntimeError: If the CopilotKit agent is not yet initialized.
97
97
  """
98
98
  if self._copilotkit_agent_instance is None:
99
- raise RuntimeError("CopilotKit agent not initialized. Call initialize() first.")
99
+ raise RuntimeError(
100
+ "CopilotKit agent not initialized. Call initialize() first."
101
+ )
100
102
  return self._copilotkit_agent_instance
101
103
 
102
104
  @property
@@ -134,7 +136,7 @@ class LanggraphAgent(agent_base.BaseAgent):
134
136
  # Observability (provider-agnostic)
135
137
  if observability_config:
136
138
  handlers, infos = observability.create_observability_handlers(
137
- observability_config # type: ignore[arg-type]
139
+ observability_config # type: ignore[arg-type]
138
140
  )
139
141
  self._obs_callbacks = []
140
142
  for handler in handlers:
@@ -205,7 +207,7 @@ class LanggraphAgent(agent_base.BaseAgent):
205
207
 
206
208
  self._copilotkit_agent_instance = LangGraphAGUIAgent(
207
209
  name=self._name,
208
- description="Agent description", # TODO: add agent description
210
+ description="Agent description", # TODO: add agent description
209
211
  graph=self._agent_instance,
210
212
  config={"callbacks": self._obs_callbacks} if self._obs_callbacks else None,
211
213
  )
@@ -292,7 +294,8 @@ class LanggraphAgent(agent_base.BaseAgent):
292
294
  # Try loading as a file path first
293
295
  try:
294
296
  import os
295
- print("Current directory: ", os.getcwd()) # TODO remove
297
+
298
+ print("Current directory: ", os.getcwd()) # TODO remove
296
299
  from pathlib import Path
297
300
 
298
301
  resolved_path = Path(module_path).resolve()
@@ -310,16 +313,23 @@ class LanggraphAgent(agent_base.BaseAgent):
310
313
  spec.loader.exec_module(module)
311
314
 
312
315
  graph_builder = getattr(module, graph_variable_name)
313
- return self._validate_graph_builder(graph_builder, module_path, graph_variable_name)
316
+ return self._validate_graph_builder(
317
+ graph_builder, module_path, graph_variable_name
318
+ )
314
319
 
315
320
  except (FileNotFoundError, ImportError):
316
321
  # Fallback: try loading as a python module
317
322
  try:
318
- module = importlib.import_module(module_path)
323
+ module_import_path = (
324
+ module_path[:-3] if module_path.endswith(".py") else module_path
325
+ )
326
+ module = importlib.import_module(module_import_path)
319
327
  graph_builder = getattr(module, graph_variable_name)
320
- return self._validate_graph_builder(graph_builder, module_path, graph_variable_name)
328
+ return self._validate_graph_builder(
329
+ graph_builder, module_path, graph_variable_name
330
+ )
321
331
  except ImportError as e:
322
- raise ValueError(
332
+ raise ValueError(
323
333
  f"Failed to load agent from {graph_definition}. Checked file path and python module: {e}"
324
334
  ) from e
325
335
  except AttributeError as e:
@@ -327,19 +337,21 @@ class LanggraphAgent(agent_base.BaseAgent):
327
337
  f"Variable '{graph_variable_name}' not found in module {module_path}: {e}"
328
338
  ) from e
329
339
  except Exception as e:
330
- raise ValueError(
340
+ raise ValueError(
331
341
  f"Failed to load agent from {graph_definition}: {e}"
332
342
  ) from e
333
343
 
334
- def _validate_graph_builder(self, graph_builder: Any, module_path: str, graph_variable_name: str) -> StateGraph:
335
- # TODO to remove, dirty fix for template deepagent langgraph
344
+ def _validate_graph_builder(
345
+ self, graph_builder: Any, module_path: str, graph_variable_name: str
346
+ ) -> StateGraph:
347
+ # TODO to remove, dirty fix for template deepagent langgraph
336
348
  if not isinstance(graph_builder, StateGraph) and not isinstance(
337
349
  graph_builder, CompiledStateGraph
338
350
  ):
339
351
  raise TypeError(
340
352
  f"The variable '{graph_variable_name}' from {module_path} is not a StateGraph instance."
341
353
  )
342
- return graph_builder # type: ignore[return-value]
354
+ return graph_builder # type: ignore[return-value]
343
355
 
344
356
  async def invoke(self, message: Any) -> Any:
345
357
  """Process a single input to chat with the agent.
@@ -53,6 +53,7 @@ class ConfigBuilder:
53
53
  self._mcp_servers: list[MCPServer] | None = None
54
54
  self._observability: list[ObservabilityConfig] | None = None
55
55
  self._guardrails: Guardrails | None = None
56
+
56
57
  def with_api_port(self, port: int) -> "ConfigBuilder":
57
58
  """Set the API port for the server.
58
59
 
@@ -126,15 +127,20 @@ class ConfigBuilder:
126
127
  raise YAMLError(f"Failed to parse yaml file for Guardrails: {e}") from e
127
128
 
128
129
  try:
129
- observability_list = yaml_config.get("engine_config", {}).get("observability")
130
+ observability_list = yaml_config.get("engine_config", {}).get(
131
+ "observability"
132
+ )
130
133
  if observability_list:
131
134
  self._observability = [
132
- ObservabilityConfig.model_validate(obs) for obs in observability_list
135
+ ObservabilityConfig.model_validate(obs)
136
+ for obs in observability_list
133
137
  ]
134
138
  else:
135
139
  self._observability = None
136
140
  except Exception as e:
137
- raise YAMLError(f"Failed to parse yaml file for Observability: {e}") from e
141
+ raise YAMLError(
142
+ f"Failed to parse yaml file for Observability: {e}"
143
+ ) from e
138
144
  # try:
139
145
  # mcp_servers_list = yaml_config.get("engine_config", {}).get("mcp_servers") or yaml_config.get("engine_config", {}).get("mcpServers") # TODO to fix camelcase issues
140
146
  # if mcp_servers_list:
@@ -310,7 +316,8 @@ class ConfigBuilder:
310
316
  if agent_type == AgentFramework.LANGGRAPH:
311
317
  from idun_agent_engine.agent.langgraph.langgraph import LanggraphAgent
312
318
  import os
313
- print("Current directory: ", os.getcwd()) # TODO remove
319
+
320
+ print("Current directory: ", os.getcwd()) # TODO remove
314
321
  try:
315
322
  validated_config = LangGraphAgentConfig.model_validate(agent_config_obj)
316
323
 
@@ -423,14 +430,17 @@ class ConfigBuilder:
423
430
  try:
424
431
  validated_config = AdkAgentConfig.model_validate(agent_config_obj)
425
432
  except Exception as e:
426
- raise ValueError(f"Cannot validate into a AdkAgentConfig model. Got {agent_config_obj}") from e
433
+ raise ValueError(
434
+ f"Cannot validate into a AdkAgentConfig model. Got {agent_config_obj}"
435
+ ) from e
427
436
  agent_instance = AdkAgent()
428
437
  else:
429
438
  raise ValueError(f"Unsupported agent type: {agent_type}")
430
439
 
431
440
  # Initialize the agent with its configuration
432
441
  await agent_instance.initialize(
433
- validated_config, observability_config#, mcp_registry=mcp_registry
442
+ validated_config,
443
+ observability_config, # , mcp_registry=mcp_registry
434
444
  ) # type: ignore[arg-type]
435
445
  return agent_instance
436
446
 
@@ -54,9 +54,7 @@ async def configure_app(app: FastAPI, engine_config):
54
54
 
55
55
  # Use ConfigBuilder's centralized agent initialization, passing the registry
56
56
  try:
57
- agent_instance = await ConfigBuilder.initialize_agent_from_config(
58
- engine_config
59
- )
57
+ agent_instance = await ConfigBuilder.initialize_agent_from_config(engine_config)
60
58
  except Exception as e:
61
59
  raise ValueError(
62
60
  f"Error retrieving agent instance from ConfigBuilder: {e}"
@@ -66,7 +64,7 @@ async def configure_app(app: FastAPI, engine_config):
66
64
  app.state.config = engine_config
67
65
  app.state.engine_config = engine_config
68
66
 
69
- app.state.guardrails = guardrails # TODO: to reactivate
67
+ app.state.guardrails = guardrails
70
68
  agent_name = getattr(agent_instance, "name", "Unknown")
71
69
  print(f"✅ Agent '{agent_name}' initialized and ready to serve!")
72
70
 
@@ -89,7 +87,6 @@ async def configure_app(app: FastAPI, engine_config):
89
87
  # print(f"🔌 MCP servers ready: {servers}")
90
88
 
91
89
 
92
-
93
90
  @asynccontextmanager
94
91
  async def lifespan(app: FastAPI):
95
92
  """FastAPI lifespan context to initialize and teardown the agent."""
@@ -3,6 +3,10 @@
3
3
  import logging
4
4
  from typing import Annotated
5
5
 
6
+ from ag_ui.core.types import RunAgentInput
7
+ from ag_ui.encoder import EventEncoder
8
+ from ag_ui_adk import ADKAgent as ADKAGUIAgent
9
+ from copilotkit import LangGraphAGUIAgent
6
10
  from fastapi import APIRouter, Depends, HTTPException, Request, status
7
11
  from fastapi.responses import StreamingResponse
8
12
  from idun_agent_schema.engine.api import ChatRequest, ChatResponse
@@ -11,11 +15,6 @@ from idun_agent_schema.engine.guardrails import Guardrail
11
15
  from idun_agent_engine.agent.base import BaseAgent
12
16
  from idun_agent_engine.server.dependencies import get_agent, get_copilotkit_agent
13
17
 
14
- from ag_ui.core.types import RunAgentInput
15
- from ag_ui.encoder import EventEncoder
16
- from copilotkit import LangGraphAGUIAgent
17
- from ag_ui_adk import ADKAgent as ADKAGUIAgent
18
-
19
18
  logging.basicConfig(
20
19
  format="%(asctime)s %(levelname)-8s %(message)s",
21
20
  level=logging.INFO,
@@ -26,14 +25,23 @@ logger = logging.getLogger(__name__)
26
25
  agent_router = APIRouter()
27
26
 
28
27
 
28
+ def _format_deep_agent_response(response_content: list[dict[str, str]]) -> str:
29
+ """Deep Research Agent responds with a list contaning a single dict: {'type': 'text', 'text': 'Your text'}."""
30
+ try:
31
+ response = response_content[0]["text"]
32
+ return response
33
+ except KeyError as k:
34
+ raise ValueError("Cannot parse Deep Research Agent's response") from k
35
+
36
+
29
37
  def _run_guardrails(
30
38
  guardrails: list[Guardrail], message: dict[str, str] | str, position: str
31
39
  ) -> None:
32
40
  """Validates the request's message, by running it on given guardrails. If input is a dict -> input, else its an output guardrails."""
33
41
  text = message["query"] if isinstance(message, dict) else message
34
42
  for guard in guardrails:
35
- if guard.position == position and not guard.validate(text): # type: ignore[attr-defined]
36
- raise HTTPException(status_code=429, detail=guard.reject_message) # type: ignore[attr-defined]
43
+ if guard.position == position and not guard.validate(text): # type: ignore[attr-defined]
44
+ raise HTTPException(status_code=429, detail=guard.reject_message) # type: ignore[attr-defined]
37
45
 
38
46
 
39
47
  @agent_router.get("/config")
@@ -60,7 +68,7 @@ async def invoke(
60
68
  """Process a chat message with the agent without streaming."""
61
69
  try:
62
70
  message = {"query": chat_request.query, "session_id": chat_request.session_id}
63
- guardrails = getattr(request.app.state, 'guardrails', [])
71
+ guardrails = getattr(request.app.state, "guardrails", [])
64
72
  if guardrails:
65
73
  _run_guardrails(guardrails, message, position="input")
66
74
  response_content = await agent.invoke(
@@ -68,7 +76,14 @@ async def invoke(
68
76
  )
69
77
  if guardrails:
70
78
  _run_guardrails(guardrails, response_content, position="output")
79
+
80
+ if agent.name == "Deep Research Agent":
81
+ return ChatResponse(
82
+ session_id=message["session_id"],
83
+ response=_format_deep_agent_response(response_content),
84
+ )
71
85
  return ChatResponse(session_id=message["session_id"], response=response_content)
86
+
72
87
  except Exception as e: # noqa: BLE001
73
88
  raise HTTPException(status_code=500, detail=str(e)) from e
74
89
 
@@ -89,6 +104,7 @@ async def stream(
89
104
  except Exception as e: # noqa: BLE001
90
105
  raise HTTPException(status_code=500, detail=str(e)) from e
91
106
 
107
+
92
108
  @agent_router.post("/copilotkit/stream")
93
109
  async def copilotkit_stream(
94
110
  input_data: RunAgentInput,
@@ -140,7 +156,7 @@ async def copilotkit_stream(
140
156
  exc_info=True,
141
157
  )
142
158
  # Create a RunErrorEvent for encoding failures
143
- from ag_ui.core import RunErrorEvent, EventType
159
+ from ag_ui.core import EventType, RunErrorEvent
144
160
 
145
161
  error_event = RunErrorEvent(
146
162
  type=EventType.RUN_ERROR,
@@ -163,7 +179,7 @@ async def copilotkit_stream(
163
179
  # ADKAgent should have yielded a RunErrorEvent, but if something went wrong
164
180
  # in the async generator itself, we need to handle it
165
181
  try:
166
- from ag_ui.core import RunErrorEvent, EventType
182
+ from ag_ui.core import EventType, RunErrorEvent
167
183
 
168
184
  error_event = RunErrorEvent(
169
185
  type=EventType.RUN_ERROR,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: idun-agent-engine
3
- Version: 0.3.0
3
+ Version: 0.3.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
@@ -33,7 +33,7 @@ Requires-Dist: google-adk<2.0.0,>=1.19.0
33
33
  Requires-Dist: google-cloud-logging<4.0.0,>=3.10.0
34
34
  Requires-Dist: guardrails-ai<0.8.0,>=0.7.0
35
35
  Requires-Dist: httpx<0.29.0,>=0.28.1
36
- Requires-Dist: idun-agent-schema<1.0.0,>=0.2.7
36
+ Requires-Dist: idun-agent-schema<1.0.0,>=0.3.1
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
39
  Requires-Dist: langchain-mcp-adapters<0.2.0,>=0.1.0
@@ -1,5 +1,5 @@
1
1
  idun_agent_engine/__init__.py,sha256=PhOL6foq5V0eXaoXw7xKUeCWXIWrOHrAFB8OuJnBqyM,550
2
- idun_agent_engine/_version.py,sha256=0EcilWMIT4cjN03dXuEtQDhswH9tkXZPcYqYHIbsc-o,72
2
+ idun_agent_engine/_version.py,sha256=7BdLKK9bjmk2rdX4sIoYIOBM826NN6_v_3RnCieDd0s,72
3
3
  idun_agent_engine/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  idun_agent_engine/agent/__init__.py,sha256=foyOoRdI_04q1b6f2A5EXEpWSCKjZxpgWMWrKcsHNl8,220
5
5
  idun_agent_engine/agent/base.py,sha256=c-3gljSHQpm6aY0JNDmXkaPtcW55rXdsI8Cgv9l4bCs,3294
@@ -10,10 +10,10 @@ idun_agent_engine/agent/haystack/haystack.py,sha256=k4NAx_zTBO9uiExM9NtuDAN94H1l
10
10
  idun_agent_engine/agent/haystack/haystack_model.py,sha256=EtOYnsWRufcrQufTRMeB3V-rZVQqfnmwKwPsYGfZdCs,362
11
11
  idun_agent_engine/agent/haystack/utils.py,sha256=sKRoPhzZWFw1NPsYwCockafzMBCCq3lGOrndbNE_C3M,609
12
12
  idun_agent_engine/agent/langgraph/__init__.py,sha256=CoBdkp9P4livdy5B0bvj9o7ftoqKmXEr9cZv4TZLncs,107
13
- idun_agent_engine/agent/langgraph/langgraph.py,sha256=ozc0ClaAl4B-_dSxiRt8KO2oxGIwNI_m-Hyk2qyJV_c,22641
13
+ idun_agent_engine/agent/langgraph/langgraph.py,sha256=vM5ppt0s_2izzZVbVXXGXGCVUGSN-GZhvQ5-6YbOgVM,22904
14
14
  idun_agent_engine/core/__init__.py,sha256=F0DMDlWcSWS_1dvh3xMbrdcVvZRHVnoAFFgREuSJfBI,408
15
15
  idun_agent_engine/core/app_factory.py,sha256=XiLrctFT_n8LP3flKFwJoJDbiWPiw98N9lbkpR8P1O0,2597
16
- idun_agent_engine/core/config_builder.py,sha256=j_gia6z66Xun2ZOtaO4TWwRMfAIA6lnk8IGaRMJKEZM,25484
16
+ idun_agent_engine/core/config_builder.py,sha256=Q6f7lITqIHFlAfXEIfQvz_6s_GVFc4zVotOFF_YTFho,25641
17
17
  idun_agent_engine/core/engine_config.py,sha256=IR8WhbenDstNSL7ORrUW8AnzgS3exFQxtwip66pFhcM,545
18
18
  idun_agent_engine/core/server_runner.py,sha256=vLlgLQM-xyvFgJMgFW2eWZoN1oc0x9FGL6bH8WsF6O8,4897
19
19
  idun_agent_engine/guardrails/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -37,10 +37,10 @@ idun_agent_engine/observability/phoenix_local/__init__.py,sha256=m9dIw1GWGKAW4wP
37
37
  idun_agent_engine/observability/phoenix_local/phoenix_local_handler.py,sha256=wjOZuMpAxdD5D33rzxycNEzFMunETpPnYjiHjbjz5GA,4252
38
38
  idun_agent_engine/server/__init__.py,sha256=WaFektUsy37bNg2niAUy_TykzStukgWPnxC-t49CEwo,177
39
39
  idun_agent_engine/server/dependencies.py,sha256=MVH8STOQ8wu-iYE_28y5dvw5FGT5PX0uQl0ldkpxw6Y,2080
40
- idun_agent_engine/server/lifespan.py,sha256=REB93NTAivgYtZ9-7xFKb5RdDZSy3IrMAF5LM39-SAo,3886
40
+ idun_agent_engine/server/lifespan.py,sha256=whWv7Gsl3CI_C13vWxl4wODOzlxIPRKSe58-_8B4zI8,3840
41
41
  idun_agent_engine/server/server_config.py,sha256=RYA7Y0c5aRw_WXaX8svFUIEtTPqzn3o-WQRm2p52C6g,213
42
42
  idun_agent_engine/server/routers/__init__.py,sha256=BgNzSVvHtGPGn5zhXhomwpKlDYBkeFi7xCbdcWVOgc8,102
43
- idun_agent_engine/server/routers/agent.py,sha256=OtviTU3nClyEHHUR5mJOMJvaNgcGR5CAkD5dGMA6Clk,8392
43
+ idun_agent_engine/server/routers/agent.py,sha256=HQkPRYFE5CadpzEQ3La8kK7lt5QUVuZTk-rzhZg9EsU,8995
44
44
  idun_agent_engine/server/routers/agui.py,sha256=Z1G4fuo57MazQWfp7ao8QZ1or2H9BXLS_JB1nFPXAkE,1891
45
45
  idun_agent_engine/server/routers/base.py,sha256=wICOXCokCIRjmHuDPDTWqeXqOVPes1CtDtiR_HvtsF0,3756
46
46
  idun_agent_engine/templates/__init__.py,sha256=xxbJZXaX6VEm_UrqzAOQcuujpEji5yqYzwQfwiqig8o,31
@@ -52,9 +52,9 @@ idun_platform_cli/main.py,sha256=jWL7Ob0p4KdRUqgPTP_EB68n7z2LyMKC2DeUsfWlBO4,200
52
52
  idun_platform_cli/groups/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
53
  idun_platform_cli/groups/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
54
  idun_platform_cli/groups/agent/main.py,sha256=QMGQi3JZ76SeFI3miIjVWpMt0L-hGz5FwxtTPQX4-Uw,301
55
- idun_platform_cli/groups/agent/package.py,sha256=CdZCbqmDG_PFoI1EFPn6Ibl9Bexel_8eO7XgmzYVCRg,2525
55
+ idun_platform_cli/groups/agent/package.py,sha256=LdIFAcfrlUcCssmSliYQIi0NFMuVkpx6t8WhMHATan8,2525
56
56
  idun_platform_cli/groups/agent/serve.py,sha256=2AbL0G1WqR33jlyiGaNvAoPZ3G1o52KYUptz_HaAjIg,3863
57
- idun_agent_engine-0.3.0.dist-info/METADATA,sha256=prVc5VpdJJCfRNPVUTZyUxZmF4DCCC9wxpTC9TA7X-c,10648
58
- idun_agent_engine-0.3.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
59
- idun_agent_engine-0.3.0.dist-info/entry_points.txt,sha256=XG3oxlSOaCrYKT1oyhKa0Ag1iJPMZ-WF6gaV_mzIJW4,52
60
- idun_agent_engine-0.3.0.dist-info/RECORD,,
57
+ idun_agent_engine-0.3.2.dist-info/METADATA,sha256=3mHURTBewd-c5G3EwzKxEANkXnD6VUMO2N7zmoeobF0,10648
58
+ idun_agent_engine-0.3.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
59
+ idun_agent_engine-0.3.2.dist-info/entry_points.txt,sha256=XG3oxlSOaCrYKT1oyhKa0Ag1iJPMZ-WF6gaV_mzIJW4,52
60
+ idun_agent_engine-0.3.2.dist-info/RECORD,,
@@ -39,8 +39,8 @@ def generate_dockerfile(dependency: Dependency) -> str:
39
39
  requirements_dockerfile = f"""FROM python:3.12-slim
40
40
  RUN apt-get update && pip install uv
41
41
 
42
- RUN uv pip install idun-agent-schema==0.3.0 --system
43
- RUN uv pip install idun-agent-engine==0.3.0 --system
42
+ RUN uv pip install idun-agent-schema==0.3.1 --system
43
+ RUN uv pip install idun-agent-engine==0.3.1 --system
44
44
 
45
45
  COPY . .
46
46
  RUN uv pip install -r requirements.txt --system