agentkernel 0.2.5__tar.gz → 0.2.7__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 (83) hide show
  1. {agentkernel-0.2.5 → agentkernel-0.2.7}/PKG-INFO +4 -2
  2. {agentkernel-0.2.5 → agentkernel-0.2.7}/pyproject.toml +5 -3
  3. agentkernel-0.2.7/src/agentkernel/adk.py +8 -0
  4. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/api/__init__.py +2 -2
  5. {agentkernel-0.2.5/src/agentkernel → agentkernel-0.2.7/src/agentkernel/api}/a2a/a2a.py +2 -2
  6. agentkernel-0.2.5/src/agentkernel/api/a2a.py → agentkernel-0.2.7/src/agentkernel/api/a2a/handler.py +1 -1
  7. agentkernel-0.2.7/src/agentkernel/api/handler.py +131 -0
  8. agentkernel-0.2.5/src/agentkernel/api/restapi.py → agentkernel-0.2.7/src/agentkernel/api/http.py +4 -5
  9. {agentkernel-0.2.5/src/agentkernel → agentkernel-0.2.7/src/agentkernel/api}/mcp/akmcp.py +2 -2
  10. agentkernel-0.2.7/src/agentkernel/aws.py +8 -0
  11. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/core/__init__.py +12 -1
  12. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/core/base.py +52 -3
  13. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/core/builder.py +14 -6
  14. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/core/config.py +12 -1
  15. agentkernel-0.2.7/src/agentkernel/core/hooks.py +74 -0
  16. agentkernel-0.2.7/src/agentkernel/core/model.py +106 -0
  17. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/core/runtime.py +121 -6
  18. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/core/service.py +38 -5
  19. {agentkernel-0.2.5/src/agentkernel/core/sessions → agentkernel-0.2.7/src/agentkernel/core/session}/__init__.py +0 -2
  20. agentkernel-0.2.7/src/agentkernel/core/session/dynamodb.py +247 -0
  21. {agentkernel-0.2.5/src/agentkernel/core/sessions → agentkernel-0.2.7/src/agentkernel/core/session}/in_memory.py +1 -1
  22. {agentkernel-0.2.5/src/agentkernel/core/sessions → agentkernel-0.2.7/src/agentkernel/core/session}/redis.py +8 -42
  23. agentkernel-0.2.7/src/agentkernel/core/session/serde.py +38 -0
  24. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/core/util/config_yaml_util.py +6 -9
  25. agentkernel-0.2.7/src/agentkernel/core/util/key_value_cache.py +120 -0
  26. agentkernel-0.2.7/src/agentkernel/crewai.py +8 -0
  27. agentkernel-0.2.7/src/agentkernel/deployment/aws/aklambda.py +103 -0
  28. {agentkernel-0.2.5/src/agentkernel → agentkernel-0.2.7/src/agentkernel/framework}/adk/adk.py +36 -15
  29. {agentkernel-0.2.5/src/agentkernel → agentkernel-0.2.7/src/agentkernel/framework}/crewai/crewai.py +33 -8
  30. {agentkernel-0.2.5/src/agentkernel → agentkernel-0.2.7/src/agentkernel/framework}/langgraph/langgraph.py +32 -12
  31. {agentkernel-0.2.5/src/agentkernel → agentkernel-0.2.7/src/agentkernel/framework}/openai/openai.py +35 -11
  32. {agentkernel-0.2.5/src/agentkernel/integrations → agentkernel-0.2.7/src/agentkernel/integration}/messenger/README.md +1 -1
  33. {agentkernel-0.2.5/src/agentkernel/integrations → agentkernel-0.2.7/src/agentkernel/integration}/slack/README.md +2 -2
  34. {agentkernel-0.2.5/src/agentkernel/integrations → agentkernel-0.2.7/src/agentkernel/integration}/slack/__init__.py +1 -1
  35. {agentkernel-0.2.5/src/agentkernel/integrations → agentkernel-0.2.7/src/agentkernel/integration}/whatsapp/README.md +3 -3
  36. {agentkernel-0.2.5/src/agentkernel/integrations → agentkernel-0.2.7/src/agentkernel/integration}/whatsapp/__init__.py +1 -1
  37. agentkernel-0.2.7/src/agentkernel/langgraph.py +8 -0
  38. agentkernel-0.2.7/src/agentkernel/mcp.py +8 -0
  39. agentkernel-0.2.7/src/agentkernel/messenger.py +8 -0
  40. agentkernel-0.2.7/src/agentkernel/openai.py +8 -0
  41. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/slack.py +1 -1
  42. agentkernel-0.2.7/src/agentkernel/trace/langfuse/__init__.py +0 -0
  43. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/trace/langfuse/adk.py +7 -5
  44. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/trace/langfuse/crewai.py +7 -5
  45. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/trace/langfuse/langgraph.py +27 -8
  46. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/trace/langfuse/openai.py +7 -5
  47. agentkernel-0.2.7/src/agentkernel/trace/openllmetry/__init__.py +0 -0
  48. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/whatsapp.py +1 -1
  49. agentkernel-0.2.5/src/agentkernel/api/agent.py +0 -93
  50. agentkernel-0.2.5/src/agentkernel/api/rest_request_handler.py +0 -26
  51. agentkernel-0.2.5/src/agentkernel/aws/aklambda.py +0 -93
  52. agentkernel-0.2.5/src/agentkernel/messenger.py +0 -8
  53. {agentkernel-0.2.5 → agentkernel-0.2.7}/README.md +0 -0
  54. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/__init__.py +0 -0
  55. {agentkernel-0.2.5/src/agentkernel → agentkernel-0.2.7/src/agentkernel/api}/a2a/__init__.py +0 -0
  56. {agentkernel-0.2.5/src/agentkernel → agentkernel-0.2.7/src/agentkernel/api}/mcp/__init__.py +0 -0
  57. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/cli/__init__.py +0 -0
  58. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/cli/cli.py +0 -0
  59. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/core/module.py +0 -0
  60. {agentkernel-0.2.5/src/agentkernel/core/sessions → agentkernel-0.2.7/src/agentkernel/core/session}/base.py +0 -0
  61. {agentkernel-0.2.5/src/agentkernel/trace/langfuse → agentkernel-0.2.7/src/agentkernel/deployment}/__init__.py +0 -0
  62. {agentkernel-0.2.5/src/agentkernel → agentkernel-0.2.7/src/agentkernel/deployment}/aws/__init__.py +0 -0
  63. {agentkernel-0.2.5/src/agentkernel/trace/openllmetry → agentkernel-0.2.7/src/agentkernel/framework}/__init__.py +0 -0
  64. {agentkernel-0.2.5/src/agentkernel → agentkernel-0.2.7/src/agentkernel/framework}/adk/__init__.py +0 -0
  65. {agentkernel-0.2.5/src/agentkernel → agentkernel-0.2.7/src/agentkernel/framework}/crewai/__init__.py +0 -0
  66. {agentkernel-0.2.5/src/agentkernel → agentkernel-0.2.7/src/agentkernel/framework}/langgraph/__init__.py +0 -0
  67. {agentkernel-0.2.5/src/agentkernel → agentkernel-0.2.7/src/agentkernel/framework}/openai/__init__.py +0 -0
  68. {agentkernel-0.2.5/src/agentkernel/integrations → agentkernel-0.2.7/src/agentkernel/integration}/__init__.py +0 -0
  69. {agentkernel-0.2.5/src/agentkernel/integrations → agentkernel-0.2.7/src/agentkernel/integration}/messenger/__init__.py +0 -0
  70. {agentkernel-0.2.5/src/agentkernel/integrations → agentkernel-0.2.7/src/agentkernel/integration}/messenger/messenger_chat.py +0 -0
  71. {agentkernel-0.2.5/src/agentkernel/integrations → agentkernel-0.2.7/src/agentkernel/integration}/slack/slack_chat.py +0 -0
  72. {agentkernel-0.2.5/src/agentkernel/integrations → agentkernel-0.2.7/src/agentkernel/integration}/whatsapp/whatsapp_chat.py +0 -0
  73. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/test/__init__.py +0 -0
  74. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/test/test.py +0 -0
  75. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/trace/__init__.py +0 -0
  76. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/trace/base.py +0 -0
  77. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/trace/langfuse/langfuse.py +0 -0
  78. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/trace/openllmetry/adk.py +0 -0
  79. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/trace/openllmetry/crewai.py +0 -0
  80. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/trace/openllmetry/langgraph.py +0 -0
  81. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/trace/openllmetry/openai.py +0 -0
  82. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/trace/openllmetry/openllmetry.py +0 -0
  83. {agentkernel-0.2.5 → agentkernel-0.2.7}/src/agentkernel/trace/trace.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: agentkernel
3
- Version: 0.2.5
3
+ Version: 0.2.7
4
4
  Summary: Agent Kernel - Unified AI Agents Runtime
5
5
  Author: Yaala Labs
6
6
  Author-email: Yaala Labs <agentkernel@yaalalabs.com>
@@ -10,7 +10,6 @@ Requires-Dist: pydantic>=2.11.7
10
10
  Requires-Dist: pydantic-settings>=2.10.1
11
11
  Requires-Dist: pyyaml>=6.0.2
12
12
  Requires-Dist: singleton-type>=0.0.5
13
- Requires-Dist: redis>=6.4.0
14
13
  Requires-Dist: a2a-sdk[http-server]>=0.3.6 ; extra == 'a2a'
15
14
  Requires-Dist: google-adk>=1.14.1 ; extra == 'adk'
16
15
  Requires-Dist: litellm~=1.74.3 ; extra == 'adk'
@@ -18,6 +17,7 @@ Requires-Dist: openinference-instrumentation-google-adk>=0.1.6 ; extra == 'adk'
18
17
  Requires-Dist: fastapi>=0.118.0 ; extra == 'api'
19
18
  Requires-Dist: uvicorn>=0.37.0 ; extra == 'api'
20
19
  Requires-Dist: gunicorn>=23.0.0 ; extra == 'api'
20
+ Requires-Dist: boto3>=1.41.4 ; extra == 'aws'
21
21
  Requires-Dist: crewai>=0.150.0 ; extra == 'crewai'
22
22
  Requires-Dist: openinference-instrumentation-crewai>=0.1.16 ; extra == 'crewai'
23
23
  Requires-Dist: openinference-instrumentation-litellm>=0.1.28 ; extra == 'crewai'
@@ -32,6 +32,7 @@ Requires-Dist: httpx>=0.27.0 ; extra == 'messenger'
32
32
  Requires-Dist: openai-agents>=0.2.3 ; extra == 'openai'
33
33
  Requires-Dist: openinference-instrumentation-openai-agents>=1.3.0 ; extra == 'openai'
34
34
  Requires-Dist: traceloop-sdk>=0.48.0 ; extra == 'openllmetry'
35
+ Requires-Dist: redis>=7.1.0 ; extra == 'redis'
35
36
  Requires-Dist: slack-bolt==1.22.0 ; extra == 'slack'
36
37
  Requires-Dist: pytest>=8.4.1 ; extra == 'test'
37
38
  Requires-Dist: pytest-asyncio>=1.2.0 ; extra == 'test'
@@ -53,6 +54,7 @@ Provides-Extra: mcp
53
54
  Provides-Extra: messenger
54
55
  Provides-Extra: openai
55
56
  Provides-Extra: openllmetry
57
+ Provides-Extra: redis
56
58
  Provides-Extra: slack
57
59
  Provides-Extra: test
58
60
  Provides-Extra: whatsapp
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "agentkernel"
7
- version = "0.2.5"
7
+ version = "0.2.7"
8
8
  description = "Agent Kernel - Unified AI Agents Runtime"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -18,7 +18,6 @@ dependencies = [
18
18
  "pydantic-settings>=2.10.1",
19
19
  "pyyaml>=6.0.2",
20
20
  "singleton-type>=0.0.5",
21
- "redis>=6.4.0",
22
21
  ]
23
22
 
24
23
  [project.optional-dependencies]
@@ -44,7 +43,10 @@ cli = [
44
43
 
45
44
  ]
46
45
  aws = [
47
-
46
+ "boto3>=1.41.4",
47
+ ]
48
+ redis = [
49
+ "redis>=7.1.0",
48
50
  ]
49
51
  openai = [
50
52
  "openai-agents>=0.2.3",
@@ -0,0 +1,8 @@
1
+ import importlib.metadata
2
+
3
+ try:
4
+ __version__ = importlib.metadata.version("agentkernel")
5
+ except importlib.metadata.PackageNotFoundError:
6
+ __version__ = "0.1.0"
7
+
8
+ from .framework.adk import *
@@ -11,5 +11,5 @@ try:
11
11
  except importlib.metadata.PackageNotFoundError:
12
12
  __version__ = "0.1.0"
13
13
 
14
- from .rest_request_handler import RESTRequestHandler
15
- from .restapi import RESTAPI
14
+ from .handler import AgentRESTRequestHandler, RESTRequestHandler
15
+ from .http import RESTAPI
@@ -9,8 +9,8 @@ from a2a.types import AgentCard, InternalError, UnsupportedOperationError
9
9
  from a2a.utils import new_agent_text_message
10
10
  from a2a.utils.errors import ServerError
11
11
 
12
- from ..core import Agent, AgentService, GlobalRuntime
13
- from ..core.config import AKConfig
12
+ from ...core import Agent, AgentService, GlobalRuntime
13
+ from ...core.config import AKConfig
14
14
 
15
15
 
16
16
  class A2A:
@@ -7,7 +7,7 @@ from a2a.utils import AGENT_CARD_WELL_KNOWN_PATH
7
7
  from fastapi import APIRouter
8
8
  from pydantic import BaseModel
9
9
 
10
- from ..a2a.a2a import A2A
10
+ from .a2a import A2A
11
11
 
12
12
 
13
13
  class A2ARESTRequestHandler:
@@ -0,0 +1,131 @@
1
+ import logging
2
+ import traceback
3
+ from abc import ABC, abstractmethod
4
+ from http import HTTPStatus
5
+ from typing import Optional
6
+
7
+ from fastapi import APIRouter, HTTPException
8
+ from pydantic import BaseModel, ConfigDict
9
+
10
+ from agentkernel.core.model import AgentReplyImage, AgentReplyText, AgentRequestAny, AgentRequestText
11
+
12
+ from ..core import AgentService, GlobalRuntime
13
+
14
+
15
+ class RESTRequestHandler(ABC):
16
+ @abstractmethod
17
+ def get_router(self) -> APIRouter:
18
+ """
19
+ Returns the APIRouter instance which has configured routes
20
+ E.g.:
21
+ - GET /health: Health check
22
+ - GET /agents: List available agents
23
+
24
+ router = APIRouter()
25
+
26
+ @router.get("/health")
27
+ def health():
28
+ return {"status": "ok"}
29
+
30
+ @router.get("/agents")
31
+ def list_agents():
32
+ return {"agents": list(GlobalRuntime.instance().agents().keys())}
33
+
34
+ """
35
+ pass
36
+
37
+
38
+ class AgentRESTRequestHandler(RESTRequestHandler):
39
+ """
40
+ API routers that expose endpoints to interact with Agent Kernel.
41
+ Endpoints:
42
+ - GET /health: Health check
43
+ - GET /agents: List available agents
44
+ - POST /run: Run an agent with a prompt
45
+ Payload JSON: { "prompt": str, "agent": str | null, "session_id": str | null }
46
+ """
47
+
48
+ def __init__(self):
49
+ self._log = logging.getLogger("ak.api.agent")
50
+
51
+ class RunRequest(BaseModel):
52
+ model_config = ConfigDict(extra="allow")
53
+
54
+ prompt: str
55
+ agent: Optional[str] = None
56
+ session_id: Optional[str] = None
57
+
58
+ def get_router(self) -> APIRouter:
59
+ """
60
+ Returns the APIRouter instance.
61
+ """
62
+
63
+ router = APIRouter()
64
+
65
+ @router.get("/health")
66
+ def health():
67
+ return {"status": "ok"}
68
+
69
+ @router.get("/agents")
70
+ def list_agents():
71
+ return {"agents": list(GlobalRuntime.instance().agents().keys())}
72
+
73
+ @router.post("/run")
74
+ async def run(body: AgentRESTRequestHandler.RunRequest):
75
+ return await self.run(body)
76
+
77
+ return router
78
+
79
+ async def run(self, req: RunRequest):
80
+ """
81
+ Async method to run the agent.
82
+ :param req: Request object containing the prompt, optional agent name, and additional properties.
83
+ """
84
+ requests = []
85
+ requests.append(AgentRequestText(text=req.prompt))
86
+
87
+ # Pack additional properties into AgentRequestAny
88
+ known_fields = {"prompt", "agent", "session_id"}
89
+ for key, value in req.model_dump().items():
90
+ if key not in known_fields:
91
+ self._log.debug(f"Adding additional context: {key}={value}")
92
+ requests.append(AgentRequestAny(name=key, content=value))
93
+ service = AgentService()
94
+
95
+ try:
96
+ service.select(req.session_id, req.agent)
97
+ if not service.agent:
98
+ raise ValueError("No agent available")
99
+
100
+ result = await service.run_multi(requests=requests)
101
+ self._log.debug(f"Result: {result}")
102
+
103
+ return {
104
+ "result": (
105
+ str(result)
106
+ if isinstance(result, (AgentReplyText, AgentReplyImage))
107
+ else "Non textual result received"
108
+ ), # sending image is not supported at the moment
109
+ "session_id": service.get_response_session_id(req.session_id),
110
+ }
111
+
112
+ except HTTPException:
113
+ raise
114
+ except ValueError as e:
115
+ self._log.error(f"POST /run error: {e}\n{traceback.format_exc()}")
116
+ raise HTTPException(
117
+ status_code=HTTPStatus.BAD_REQUEST,
118
+ detail={
119
+ "error": str(e),
120
+ "session_id": service.get_response_session_id(req.session_id),
121
+ },
122
+ )
123
+ except Exception as e:
124
+ self._log.error(f"POST /run error: {e}\n{traceback.format_exc()}")
125
+ raise HTTPException(
126
+ status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
127
+ detail={
128
+ "error": str(e),
129
+ "session_id": service.get_response_session_id(None),
130
+ },
131
+ )
@@ -5,9 +5,8 @@ from fastapi import APIRouter, FastAPI
5
5
  from fastapi.middleware.cors import CORSMiddleware
6
6
  from fastapi.openapi.utils import get_openapi
7
7
 
8
- from ..api.rest_request_handler import RESTRequestHandler
9
8
  from ..core.config import AKConfig
10
- from .agent import AgentRESTRequestHandler
9
+ from .handler import AgentRESTRequestHandler, RESTRequestHandler
11
10
 
12
11
  logging.basicConfig(
13
12
  level=logging.DEBUG,
@@ -22,7 +21,7 @@ class RESTAPI:
22
21
  Can run any FastAPI app instance or assemble one from routers.
23
22
  """
24
23
 
25
- _log = logging.getLogger("ak.api.restapi")
24
+ _log = logging.getLogger("ak.api.http")
26
25
  _custom_routers = []
27
26
 
28
27
  @classmethod
@@ -79,12 +78,12 @@ class RESTAPI:
79
78
  routers.append(handler.get_router())
80
79
 
81
80
  if AKConfig.get().a2a.enabled:
82
- from .a2a import A2ARESTRequestHandler
81
+ from .a2a.handler import A2ARESTRequestHandler
83
82
 
84
83
  routers.append(A2ARESTRequestHandler.get_catalog_router())
85
84
  routers.extend(A2ARESTRequestHandler.get_agent_routers())
86
85
  if AKConfig.get().mcp.enabled:
87
- from ..mcp.akmcp import MCP
86
+ from .mcp.akmcp import MCP
88
87
 
89
88
  mcp_app = MCP.get_http_app()
90
89
  app = cls._create_app(routers=routers, lifespan=mcp_app.lifespan)
@@ -4,8 +4,8 @@ from typing import Any
4
4
  from fastmcp import Context, FastMCP
5
5
  from fastmcp.server.http import StarletteWithLifespan
6
6
 
7
- from ..core import Agent, AgentService, GlobalRuntime
8
- from ..core.config import AKConfig
7
+ from ...core import Agent, AgentService, GlobalRuntime
8
+ from ...core.config import AKConfig
9
9
 
10
10
 
11
11
  class MCP:
@@ -0,0 +1,8 @@
1
+ import importlib.metadata
2
+
3
+ try:
4
+ __version__ = importlib.metadata.version("agentkernel")
5
+ except importlib.metadata.PackageNotFoundError:
6
+ __version__ = "0.1.0"
7
+
8
+ from .deployment.aws import *
@@ -12,8 +12,19 @@ except importlib.metadata.PackageNotFoundError:
12
12
  __version__ = "0.1.0"
13
13
 
14
14
  from .base import Agent, Runner, Session
15
+ from .model import (
16
+ AgentRequest,
17
+ AgentRequestAny,
18
+ AgentRequestFile,
19
+ AgentRequestImage,
20
+ AgentRequestText,
21
+ AgentReply,
22
+ AgentReplyText,
23
+ AgentReplyImage,
24
+ )
15
25
  from .config import AKConfig as Config
16
26
  from .module import Module
17
27
  from .runtime import GlobalRuntime, Runtime
18
28
  from .service import AgentService
19
- from .sessions.redis import RedisDriver, RedisSessionSerde
29
+ from .hooks import Prehook, Posthook
30
+ from .util.key_value_cache import KeyValueCache
@@ -1,8 +1,13 @@
1
+ import contextvars
1
2
  import logging
2
3
  from abc import ABC, abstractmethod
3
4
  from typing import Any, List
4
5
 
5
6
  from .config import AKConfig
7
+ from .model import AgentReply, AgentRequest
8
+ from .util.key_value_cache import KeyValueCache
9
+
10
+ current_session = contextvars.ContextVar("session_id", default="")
6
11
 
7
12
 
8
13
  class Session:
@@ -17,6 +22,31 @@ class Session:
17
22
  the runtime configuration.
18
23
  """
19
24
 
25
+ VOLATILE_CACHE_KEY = "v_cache"
26
+ NON_VOLATILE_CACHE_KEY = "nv_cache"
27
+
28
+ @classmethod
29
+ def get_current_session_id(cls) -> str:
30
+ """
31
+ Returns the current session ID from the context variable.
32
+ :return: The current session ID.
33
+ """
34
+ return current_session.get()
35
+
36
+ def get_volatile_cache(self) -> KeyValueCache:
37
+ """
38
+ Returns the volatile key-value cache associated with this session.
39
+ :return: The volatile KeyValueCache instance.
40
+ """
41
+ return self.get(self.VOLATILE_CACHE_KEY)
42
+
43
+ def get_non_volatile_cache(self) -> KeyValueCache:
44
+ """
45
+ Returns the non-volatile key-value cache associated with this session.
46
+ :return: The non-volatile KeyValueCache instance.
47
+ """
48
+ return self.get(self.NON_VOLATILE_CACHE_KEY)
49
+
20
50
  def __init__(self, id: str):
21
51
  """
22
52
  Initializes a Session instance.
@@ -26,6 +56,12 @@ class Session:
26
56
  self._id = id
27
57
  self._data = {}
28
58
 
59
+ # Pre-initialize key-value caches to be used by application code which will not be part of the agent context
60
+ self.set(self.VOLATILE_CACHE_KEY, KeyValueCache())
61
+ self.set(self.NON_VOLATILE_CACHE_KEY, KeyValueCache())
62
+
63
+ self._token = None
64
+
29
65
  @property
30
66
  def id(self) -> str:
31
67
  """
@@ -62,6 +98,19 @@ class Session:
62
98
  self._data[key] = value
63
99
  return value
64
100
 
101
+ def set_context(self):
102
+ """
103
+ Sets the current session context variable to this session's ID.
104
+ """
105
+ self._token = current_session.set(self._id)
106
+
107
+ def reset_context(self):
108
+ """
109
+ Resets the current session context variable to the previous value.
110
+ """
111
+ if self._token:
112
+ current_session.reset(self._token)
113
+
65
114
 
66
115
  class Runner(ABC):
67
116
  """
@@ -88,12 +137,12 @@ class Runner(ABC):
88
137
  return self._name
89
138
 
90
139
  @abstractmethod
91
- async def run(self, agent: Any, session: Session, prompt: Any) -> Any:
140
+ async def run(self, agent: Any, session: Session, requests: list[AgentRequest]) -> AgentReply:
92
141
  """
93
- Runs the agent with the provided prompt.
142
+ Runs the agent with the provided multi modal inputs.
94
143
  :param agent: The agent to run.
95
144
  :param session: The session to use for the agent.
96
- :param prompt: The prompt to provide to the agent.
145
+ :param requests: The list of requests to provide to the agent.
97
146
  :return: The result of the agent's execution.
98
147
  """
99
148
  pass
@@ -2,9 +2,7 @@ import logging
2
2
  from enum import StrEnum
3
3
 
4
4
  from .config import AKConfig
5
- from .sessions import SessionStore
6
- from .sessions.in_memory import InMemorySessionStore
7
- from .sessions.redis import RedisDriver, RedisSessionStore
5
+ from .session import SessionStore
8
6
 
9
7
 
10
8
  class Builder:
@@ -29,6 +27,7 @@ class SessionStoreType(StrEnum):
29
27
 
30
28
  IN_MEMORY = "IN_MEMORY"
31
29
  REDIS = "REDIS"
30
+ DYNAMODB = "DYNAMODB"
32
31
 
33
32
  @classmethod
34
33
  def from_str(cls, type_str: str) -> "SessionStoreType":
@@ -67,9 +66,10 @@ class SessionStoreBuilder(Builder):
67
66
 
68
67
  This static method reads the session store type from the application configuration
69
68
  and instantiates the appropriate SessionStore implementation. Currently supports
70
- Redis-backed and in-memory session stores.
69
+ Redis-backed, DynamoDB-backed, and in-memory session stores.
71
70
 
72
- :returns: An instance of either RedisSessionStore (if configured type is REDIS)
71
+ :returns: An instance of RedisSessionStore (if configured type is REDIS),
72
+ DynamoDBSessionStore (if configured type is DYNAMODB),
73
73
  or InMemorySessionStore (for all other types).
74
74
 
75
75
  :raises: Any exceptions raised by SessionStoreType.from_str(), AKConfig.get(),
@@ -79,6 +79,14 @@ class SessionStoreBuilder(Builder):
79
79
 
80
80
  Builder._log.info(f"Building {session_store_type} session store")
81
81
  if session_store_type == SessionStoreType.REDIS:
82
- return RedisSessionStore(RedisDriver())
82
+ from .session.redis import RedisSessionStore
83
+
84
+ return RedisSessionStore()
85
+ elif session_store_type == SessionStoreType.DYNAMODB:
86
+ from .session.dynamodb import DynamoDBSessionStore
87
+
88
+ return DynamoDBSessionStore()
83
89
  else:
90
+ from .session.in_memory import InMemorySessionStore
91
+
84
92
  return InMemorySessionStore()
@@ -22,9 +22,20 @@ class _RedisConfig(BaseModel):
22
22
  prefix: str = Field(default="ak:sessions:", description="Key prefix for Redis session storage")
23
23
 
24
24
 
25
+ class _DynamoDBConfig(BaseModel):
26
+ table_name: str = Field(
27
+ description="DynamoDB table name for session storage. Table should have a partition key named 'session_id' and a sort key named 'key'"
28
+ )
29
+ ttl: int = Field(
30
+ default=604800,
31
+ description="DynamoDB item TTL in seconds (0 disables). Used to compute UNIX epoch 'expiry_time' attribute written per item.",
32
+ )
33
+
34
+
25
35
  class _SessionStoreConfig(BaseModel):
26
- type: str = Field(default="in_memory", pattern="^(in_memory|redis)$")
36
+ type: str = Field(default="in_memory", pattern="^(in_memory|redis|dynamodb)$")
27
37
  redis: Optional[_RedisConfig] = None
38
+ dynamodb: Optional[_DynamoDBConfig] = None
28
39
 
29
40
 
30
41
  class _RoutesConfig(BaseModel):
@@ -0,0 +1,74 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ from .base import Agent, Session
4
+ from .model import AgentReply, AgentRequest
5
+
6
+ """
7
+ Prehook and Posthook classes define the interface for hooks that can be executed before and after an agent's execution respectively.
8
+ These hooks allow for modification of prompts before execution and replies after execution, enabling functionalities such as context injection, validation, moderation, logging, and analytics.
9
+
10
+ Currently, they will get only called for the initial execution of an agent when a user prompt is provided. It's unable to hook into agent-to-agent calls within a workflow. This will be a future enhancement.
11
+ """
12
+
13
+
14
+ class Prehook(ABC):
15
+ @abstractmethod
16
+ async def on_run(
17
+ self, session: Session, agent: Agent, requests: list[AgentRequest]
18
+ ) -> list[AgentRequest] | AgentReply:
19
+ """
20
+ Hook method called before an agent starts executing a prompt. These hooks can modify the prompt or halt execution.
21
+ Some use cases:
22
+ - RAG context injection
23
+ - Prompt validation like input guard rails
24
+ - Logging or analytics
25
+
26
+ :param: session (Session): The session instance.
27
+ :param: agent (Agent): The agent that will execute the prompt.
28
+ :param: requests (list[AgentRequest]): The list of requests provided to the agent.
29
+ :return:
30
+ - AgentReply: If the hook decides to halt execution, it can return an AgentReply which will be sent
31
+ - list[AgentRequest]: The modified requests or the input list. You can modify the requests in place without taking copies
32
+ You can also add additional content to the requests list. e.g. files, images, etc.
33
+
34
+ """
35
+ raise NotImplementedError
36
+
37
+ @abstractmethod
38
+ def name(self) -> str:
39
+ """
40
+ Returns the name of the prehook.
41
+ """
42
+ raise NotImplementedError
43
+
44
+
45
+ class Posthook(ABC):
46
+ @abstractmethod
47
+ async def on_run(
48
+ self, session: Session, requests: list[AgentRequest], agent: Agent, agent_reply: AgentReply
49
+ ) -> AgentReply:
50
+ """
51
+ Hook method called after an agent finishes executing a prompt. These hooks can modify the agent's reply. Some use cases:
52
+ - Moderation of agent replies. e.g. output guardrails
53
+ - Adding disclaimers or additional information to the reply
54
+ - Logging or analytics
55
+
56
+ Note: if the hook changes the reply, the modified reply will be sent to the next hook for processing.
57
+ The agent_reply parameter contains the unmodified reply from the agent for the first posthook, and the reply modified by previous posthooks for subsequent hooks.
58
+
59
+ :param: session (Session): The session instance.
60
+ :param: requests (list[AgentRequest]): The original requests provided to the agent after any pre-execution hooks have been applied.
61
+ :param: agent (Agent): The agent that executed the prompt.
62
+ :param: agent_reply (AgentReply): The reply to process. For the first posthook, this is the unmodified
63
+ agent reply. For subsequent posthooks, this is the reply modified by previous posthooks in the chain.
64
+
65
+ :return: The modified reply. If not modified, return the current reply.
66
+ """
67
+ raise NotImplementedError
68
+
69
+ @abstractmethod
70
+ def name(self) -> str:
71
+ """
72
+ :return: the name of the posthook.
73
+ """
74
+ raise NotImplementedError
@@ -0,0 +1,106 @@
1
+ from typing import Any, Literal, Union
2
+
3
+ from pydantic import BaseModel
4
+
5
+
6
+ class AgentRequestText(BaseModel):
7
+ """
8
+ AgentRequestText encapsulates a text request to an agent.
9
+
10
+ text: str : This is the user input text
11
+ type: Literal["text"]
12
+ """
13
+
14
+ text: str
15
+ type: Literal["text"] = "text"
16
+
17
+ def __str__(self) -> str:
18
+ return self.text
19
+
20
+
21
+ class AgentRequestFile(BaseModel):
22
+ """
23
+ AgentRequestFile encapsulates a file attachment request to an agent
24
+
25
+ file_data: str : This could be base64 encoded string or url
26
+ name: str : name of the file
27
+ type: Literal["file"]
28
+ mime_type: str | None = None : Optional. The IANA standard MIME type of the file
29
+ """
30
+
31
+ file_data: str # This could be base64 encoded string or url
32
+ name: str
33
+ type: Literal["file"] = "file"
34
+ mime_type: str | None = None # Optional. The IANA standard MIME type of the source data
35
+
36
+
37
+ class AgentRequestImage(BaseModel):
38
+ """
39
+ AgentRequestImage encapsulates an image request to an agent
40
+
41
+ image_data: str : This should be base64 encoded string
42
+ name: str : name of the image
43
+ type: Literal["image"]
44
+ mime_type: str | None = None : Optional. The IANA standard MIME type of the image
45
+ """
46
+
47
+ image_data: str
48
+ name: str
49
+ type: Literal["image"] = "image"
50
+ mime_type: str | None = None
51
+
52
+
53
+ class AgentRequestAny(BaseModel):
54
+ """
55
+ AgentRequestAny encapsulates passing any type of request to be handled by the pre-execution hooks. These are not directly handled by the agent kernel runtime.
56
+
57
+ content: Any : This could be base64 encoded string or bytes or url
58
+ name: str : name of the data
59
+ type: Literal["other"]
60
+ """
61
+
62
+ content: Any
63
+ name: str
64
+ type: Literal["other"] = "other"
65
+
66
+
67
+ class AgentReplyText(AgentRequestText):
68
+ """
69
+ AgentReplyText encapsulates a text reply from an agent.
70
+
71
+ prompt: str : The text prompt sent to the agent
72
+
73
+ Inherits fields `text` and `type` from AgentRequestText.
74
+ """
75
+
76
+ prompt: str = ""
77
+
78
+ def __str__(self) -> str:
79
+ return self.text
80
+
81
+
82
+ class AgentReplyImage(BaseModel):
83
+ """
84
+ AgentReplyImage encapsulates a text & image reply from an agent.
85
+
86
+ text: str : This is the agent output text
87
+ prompt: str : The text prompt sent to the agent
88
+ image_data: str : This should be base64 encoded string
89
+ name: str : name of the image
90
+ type: Literal["image"]
91
+ mime_type: str | None = None : Optional. The IANA standard MIME type of the image
92
+ """
93
+
94
+ text: str
95
+ prompt: str = ""
96
+ image_data: str
97
+ name: str
98
+ type: Literal["image"] = "image"
99
+ mime_type: str | None = None
100
+
101
+ def __str__(self) -> str:
102
+ return f"{self.text}. Image {self.name} is attached."
103
+
104
+
105
+ type AgentRequest = Union[AgentRequestText, AgentRequestFile, AgentRequestImage, AgentRequestAny]
106
+ type AgentReply = Union[AgentReplyText, AgentReplyImage]