agentkit-sdk-python 0.1.5__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.
- agentkit/__init__.py +23 -0
- agentkit/apps/__init__.py +58 -0
- agentkit/apps/a2a_app/__init__.py +13 -0
- agentkit/apps/a2a_app/a2a_app.py +134 -0
- agentkit/apps/a2a_app/telemetry.py +119 -0
- agentkit/apps/agent_server_app/__init__.py +13 -0
- agentkit/apps/agent_server_app/agent_server_app.py +85 -0
- agentkit/apps/base_app.py +20 -0
- agentkit/apps/mcp_app/__init__.py +13 -0
- agentkit/apps/mcp_app/mcp_app.py +150 -0
- agentkit/apps/mcp_app/telemetry.py +115 -0
- agentkit/apps/simple_app/__init__.py +13 -0
- agentkit/apps/simple_app/simple_app.py +94 -0
- agentkit/apps/simple_app/simple_app_handlers.py +325 -0
- agentkit/apps/simple_app/telemetry.py +124 -0
- agentkit/apps/utils.py +45 -0
- agentkit/client/__init__.py +26 -0
- agentkit/client/base_client.py +219 -0
- agentkit/identity/__init__.py +13 -0
- agentkit/identity/auth.py +70 -0
- agentkit/knowledge/__init__.py +47 -0
- agentkit/knowledge/knowledge.py +203 -0
- agentkit/knowledge/knowledge_all_types.py +191 -0
- agentkit/mcp/__init__.py +79 -0
- agentkit/mcp/mcp.py +294 -0
- agentkit/mcp/mcp_all_types.py +1212 -0
- agentkit/memory/__init__.py +71 -0
- agentkit/memory/memory.py +236 -0
- agentkit/memory/memory_all_types.py +358 -0
- agentkit/runtime/__init__.py +13 -0
- agentkit/runtime/runtime.py +191 -0
- agentkit/runtime/runtime_all_types.py +624 -0
- agentkit/runtime/runtime_v1.py +178 -0
- agentkit/runtime/types.py +188 -0
- agentkit/toolkit/__init__.py +13 -0
- agentkit/toolkit/cli/__init__.py +13 -0
- agentkit/toolkit/cli/__main__.py +7 -0
- agentkit/toolkit/cli/cli.py +97 -0
- agentkit/toolkit/cli/cli_build.py +53 -0
- agentkit/toolkit/cli/cli_config.py +170 -0
- agentkit/toolkit/cli/cli_deploy.py +52 -0
- agentkit/toolkit/cli/cli_destroy.py +53 -0
- agentkit/toolkit/cli/cli_init.py +364 -0
- agentkit/toolkit/cli/cli_invoke.py +168 -0
- agentkit/toolkit/cli/cli_launch.py +34 -0
- agentkit/toolkit/cli/cli_status.py +53 -0
- agentkit/toolkit/cli/cli_version.py +87 -0
- agentkit/toolkit/cli/utils.py +47 -0
- agentkit/toolkit/config/__init__.py +52 -0
- agentkit/toolkit/config/auto_prompt.py +752 -0
- agentkit/toolkit/config/build_config.py +28 -0
- agentkit/toolkit/config/common_config.py +18 -0
- agentkit/toolkit/config/config.py +306 -0
- agentkit/toolkit/config/config_handler.py +331 -0
- agentkit/toolkit/config/config_manager.py +48 -0
- agentkit/toolkit/config/config_validator.py +121 -0
- agentkit/toolkit/config/constants.py +18 -0
- agentkit/toolkit/config/dataclass_utils.py +153 -0
- agentkit/toolkit/config/deploy_config.py +1 -0
- agentkit/toolkit/config/utils.py +57 -0
- agentkit/toolkit/config/workflow_configs.py +149 -0
- agentkit/toolkit/consts.py +1 -0
- agentkit/toolkit/core/__init__.py +13 -0
- agentkit/toolkit/core/build/__init__.py +13 -0
- agentkit/toolkit/core/build/base_builder.py +6 -0
- agentkit/toolkit/core/build/cloud_builder.py +0 -0
- agentkit/toolkit/core/build/local_builder.py +0 -0
- agentkit/toolkit/core/deploy/__init__.py +13 -0
- agentkit/toolkit/core/deploy/base_deployer.py +6 -0
- agentkit/toolkit/core/deploy/cloud_deployer.py +0 -0
- agentkit/toolkit/core/deploy/local_deployer.py +0 -0
- agentkit/toolkit/integrations/__init__.py +17 -0
- agentkit/toolkit/integrations/builder/__init__.py +23 -0
- agentkit/toolkit/integrations/builder/base.py +59 -0
- agentkit/toolkit/integrations/builder/local_docker_builder.py +163 -0
- agentkit/toolkit/integrations/builder/ve_core_pipeline_builder.py +853 -0
- agentkit/toolkit/integrations/container.py +843 -0
- agentkit/toolkit/integrations/runner/__init__.py +26 -0
- agentkit/toolkit/integrations/runner/base.py +222 -0
- agentkit/toolkit/integrations/runner/local_docker_runner.py +407 -0
- agentkit/toolkit/integrations/runner/ve_agentkit_runner.py +665 -0
- agentkit/toolkit/integrations/services/__init__.py +26 -0
- agentkit/toolkit/integrations/services/cr_service.py +449 -0
- agentkit/toolkit/integrations/services/tos_service.py +291 -0
- agentkit/toolkit/integrations/utils/__init__.py +21 -0
- agentkit/toolkit/integrations/utils/project_archiver.py +276 -0
- agentkit/toolkit/integrations/ve_code_pipeline.py +643 -0
- agentkit/toolkit/integrations/ve_cr.py +385 -0
- agentkit/toolkit/integrations/ve_iam.py +210 -0
- agentkit/toolkit/resources/samples/basic.py +79 -0
- agentkit/toolkit/resources/samples/basic_stream.py +100 -0
- agentkit/toolkit/resources/samples/customer_support_assistant.py +3 -0
- agentkit/toolkit/resources/samples/financial_analyst.py +140 -0
- agentkit/toolkit/resources/samples/simple_a2a_veadk.py +32 -0
- agentkit/toolkit/resources/samples/simple_app_veadk.py +55 -0
- agentkit/toolkit/resources/samples/simple_mcp_veadk.py +50 -0
- agentkit/toolkit/resources/templates/Dockerfile.j2 +27 -0
- agentkit/toolkit/resources/templates/code-pipeline-tos-cr-step.j2 +52 -0
- agentkit/toolkit/workflows/__init__.py +27 -0
- agentkit/toolkit/workflows/base.py +87 -0
- agentkit/toolkit/workflows/hybird_local_ve_workflow_v1.py +381 -0
- agentkit/toolkit/workflows/local_workflow_v1.py +262 -0
- agentkit/toolkit/workflows/ve_agentkit_workflow.py +369 -0
- agentkit/tools/__init__.py +17 -0
- agentkit/tools/tools.py +106 -0
- agentkit/tools/tools_all_types.py +337 -0
- agentkit/utils/__init__.py +41 -0
- agentkit/utils/credential.py +44 -0
- agentkit/utils/logging_config.py +366 -0
- agentkit/utils/misc.py +70 -0
- agentkit/utils/request.py +59 -0
- agentkit/utils/template_utils.py +256 -0
- agentkit/utils/ve_sign.py +247 -0
- agentkit/version.py +15 -0
- agentkit_sdk_python-0.1.5.dist-info/METADATA +262 -0
- agentkit_sdk_python-0.1.5.dist-info/RECORD +120 -0
- agentkit_sdk_python-0.1.5.dist-info/WHEEL +5 -0
- agentkit_sdk_python-0.1.5.dist-info/entry_points.txt +2 -0
- agentkit_sdk_python-0.1.5.dist-info/licenses/LICENSE +201 -0
- agentkit_sdk_python-0.1.5.dist-info/top_level.txt +1 -0
agentkit/__init__.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
# Note: BaseAgentkitClient and ApiConfig are internal infrastructure classes.
|
|
16
|
+
# Users should use the high-level service clients instead:
|
|
17
|
+
# - from agentkit.memory import AgentkitMemory
|
|
18
|
+
# - from agentkit.knowledge import AgentkitKnowledge
|
|
19
|
+
# - from agentkit.mcp import AgentkitMCP
|
|
20
|
+
# - from agentkit.runtime import AgentkitRuntime
|
|
21
|
+
# - from agentkit.tools import AgentkitTools
|
|
22
|
+
|
|
23
|
+
__all__ = []
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from typing import TYPE_CHECKING
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from agentkit.apps.a2a_app.a2a_app import AgentkitA2aApp
|
|
19
|
+
from agentkit.apps.agent_server_app.agent_server_app import AgentkitAgentServerApp
|
|
20
|
+
from agentkit.apps.mcp_app.mcp_app import AgentkitMCPApp
|
|
21
|
+
from agentkit.apps.simple_app.simple_app import AgentkitSimpleApp
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def __getattr__(
|
|
25
|
+
name,
|
|
26
|
+
) -> (
|
|
27
|
+
type["AgentkitA2aApp"]
|
|
28
|
+
| type["AgentkitMCPApp"]
|
|
29
|
+
| type["AgentkitSimpleApp"]
|
|
30
|
+
| type["AgentkitAgentServerApp"]
|
|
31
|
+
):
|
|
32
|
+
if name == "AgentkitA2aApp":
|
|
33
|
+
from agentkit.apps.a2a_app.a2a_app import AgentkitA2aApp
|
|
34
|
+
|
|
35
|
+
return AgentkitA2aApp
|
|
36
|
+
if name == "AgentkitMCPApp":
|
|
37
|
+
from agentkit.apps.mcp_app.mcp_app import AgentkitMCPApp
|
|
38
|
+
|
|
39
|
+
return AgentkitMCPApp
|
|
40
|
+
if name == "AgentkitSimpleApp":
|
|
41
|
+
from agentkit.apps.simple_app.simple_app import AgentkitSimpleApp
|
|
42
|
+
|
|
43
|
+
return AgentkitSimpleApp
|
|
44
|
+
if name == "AgentkitAgentServerApp":
|
|
45
|
+
from agentkit.apps.agent_server_app.agent_server_app import (
|
|
46
|
+
AgentkitAgentServerApp,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
return AgentkitAgentServerApp
|
|
50
|
+
raise AttributeError(f"module 'agentkit.apps' has no attribute '{name}'")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
__all__ = [
|
|
54
|
+
"AgentkitA2aApp",
|
|
55
|
+
"AgentkitMCPApp",
|
|
56
|
+
"AgentkitSimpleApp",
|
|
57
|
+
"AgentkitAgentServerApp",
|
|
58
|
+
]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
import logging
|
|
16
|
+
import time
|
|
17
|
+
from typing import Callable, override
|
|
18
|
+
|
|
19
|
+
import uvicorn
|
|
20
|
+
from a2a.server.agent_execution import AgentExecutor
|
|
21
|
+
from a2a.server.agent_execution.context import RequestContext
|
|
22
|
+
from a2a.server.apps import A2AStarletteApplication
|
|
23
|
+
from a2a.server.events.event_queue import EventQueue
|
|
24
|
+
from a2a.server.request_handlers import DefaultRequestHandler
|
|
25
|
+
from a2a.server.tasks import InMemoryTaskStore
|
|
26
|
+
from a2a.server.tasks.task_store import TaskStore
|
|
27
|
+
from a2a.types import AgentCard
|
|
28
|
+
|
|
29
|
+
from agentkit.apps.base_app import BaseAgentkitApp
|
|
30
|
+
from agentkit.apps.a2a_app.telemetry import telemetry
|
|
31
|
+
|
|
32
|
+
logger = logging.getLogger(__name__)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _wrap_agent_executor_execute_func(execute_func: Callable) -> Callable:
|
|
36
|
+
async def wrapper(*args, **kwargs):
|
|
37
|
+
executor_instance: AgentExecutor = args[0]
|
|
38
|
+
context: RequestContext = args[1]
|
|
39
|
+
event_queue: EventQueue = args[2]
|
|
40
|
+
|
|
41
|
+
with telemetry.tracer.start_as_current_span(name="a2a_invocation") as span:
|
|
42
|
+
exception = None
|
|
43
|
+
try:
|
|
44
|
+
result = await execute_func(
|
|
45
|
+
executor_instance, context=context, event_queue=event_queue
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
except Exception as e:
|
|
49
|
+
logger.error("Invoke agent execute function failed: %s", e)
|
|
50
|
+
exception = e
|
|
51
|
+
raise e
|
|
52
|
+
finally:
|
|
53
|
+
# handler trace span and metrics
|
|
54
|
+
telemetry.trace_a2a_agent(
|
|
55
|
+
execute_func,
|
|
56
|
+
span,
|
|
57
|
+
context,
|
|
58
|
+
result,
|
|
59
|
+
exception,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
return result
|
|
63
|
+
|
|
64
|
+
return wrapper
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class AgentkitA2aApp(BaseAgentkitApp):
|
|
68
|
+
def __init__(self) -> None:
|
|
69
|
+
super().__init__()
|
|
70
|
+
|
|
71
|
+
self._agent_executor: AgentExecutor | None = None
|
|
72
|
+
self._task_store: TaskStore | None = None
|
|
73
|
+
|
|
74
|
+
def agent_executor(self, **kwargs) -> Callable:
|
|
75
|
+
"""Wrap an AgentExecutor class, init it, then bind it to the app instance."""
|
|
76
|
+
|
|
77
|
+
def wrapper(cls: type) -> type[AgentExecutor]:
|
|
78
|
+
if not issubclass(cls, AgentExecutor):
|
|
79
|
+
raise TypeError(
|
|
80
|
+
f"{cls.__name__} must inherit from `a2a.server.agent_execution.AgentExecutor`"
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
if self._agent_executor:
|
|
84
|
+
raise RuntimeError("An executor is already bound to this app instance.")
|
|
85
|
+
|
|
86
|
+
# Wrap the execute method for intercepting context and event_queue
|
|
87
|
+
cls.execute = _wrap_agent_executor_execute_func(cls.execute)
|
|
88
|
+
|
|
89
|
+
# Initialize and bind the executor instance
|
|
90
|
+
self._agent_executor = cls(**kwargs)
|
|
91
|
+
|
|
92
|
+
return cls
|
|
93
|
+
|
|
94
|
+
return wrapper
|
|
95
|
+
|
|
96
|
+
def task_store(self, **kwargs) -> Callable:
|
|
97
|
+
"""Wrap a TaskStore class, init it, then bind it to the app instance."""
|
|
98
|
+
|
|
99
|
+
def wrapper(cls: type) -> type[TaskStore]:
|
|
100
|
+
if not issubclass(cls, TaskStore):
|
|
101
|
+
raise TypeError(
|
|
102
|
+
f"{cls.__name__} must inherit from `a2a.server.tasks.task_store.TaskStore`"
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
if self._task_store:
|
|
106
|
+
raise RuntimeError(
|
|
107
|
+
"A task store is already bound to this app instance."
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
self._task_store = cls(**kwargs)
|
|
111
|
+
return cls
|
|
112
|
+
|
|
113
|
+
return wrapper
|
|
114
|
+
|
|
115
|
+
@override
|
|
116
|
+
def run(self, agent_card: AgentCard, host: str, port: int = 8000):
|
|
117
|
+
if not self._agent_executor:
|
|
118
|
+
raise RuntimeError(
|
|
119
|
+
"At least one executor should be provided via `@agent_executor(...)`."
|
|
120
|
+
)
|
|
121
|
+
if not self._task_store:
|
|
122
|
+
logger.warning(
|
|
123
|
+
"No task store provided. You can provide a task store via `@task_store(...)`. Using in-memory task store instead."
|
|
124
|
+
)
|
|
125
|
+
self._task_store = InMemoryTaskStore()
|
|
126
|
+
|
|
127
|
+
a2a_app = A2AStarletteApplication(
|
|
128
|
+
agent_card=agent_card,
|
|
129
|
+
http_handler=DefaultRequestHandler(
|
|
130
|
+
agent_executor=self._agent_executor, task_store=self._task_store
|
|
131
|
+
),
|
|
132
|
+
).build()
|
|
133
|
+
|
|
134
|
+
uvicorn.run(a2a_app, host=host, port=port)
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
import time
|
|
18
|
+
from typing import Callable
|
|
19
|
+
|
|
20
|
+
from opentelemetry import trace
|
|
21
|
+
from opentelemetry.trace import get_tracer
|
|
22
|
+
from opentelemetry.metrics import get_meter
|
|
23
|
+
from opentelemetry.trace.span import Span
|
|
24
|
+
from a2a.server.agent_execution.context import RequestContext
|
|
25
|
+
from google.adk.a2a.converters.request_converter import _get_user_id
|
|
26
|
+
|
|
27
|
+
from agentkit.apps.utils import safe_serialize_to_json_string
|
|
28
|
+
|
|
29
|
+
_GEN_AI_CLIENT_OPERATION_DURATION_BUCKETS = [
|
|
30
|
+
0.01,
|
|
31
|
+
0.02,
|
|
32
|
+
0.04,
|
|
33
|
+
0.08,
|
|
34
|
+
0.16,
|
|
35
|
+
0.32,
|
|
36
|
+
0.64,
|
|
37
|
+
1.28,
|
|
38
|
+
2.56,
|
|
39
|
+
5.12,
|
|
40
|
+
10.24,
|
|
41
|
+
20.48,
|
|
42
|
+
40.96,
|
|
43
|
+
81.92,
|
|
44
|
+
163.84,
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
logger = logging.getLogger("agentkit." + __name__)
|
|
48
|
+
|
|
49
|
+
class Telemetry:
|
|
50
|
+
def __init__(self):
|
|
51
|
+
self.tracer = get_tracer("agentkit.a2a_app")
|
|
52
|
+
self.meter = get_meter("agentkit.a2a_app")
|
|
53
|
+
self.latency_histogram = self.meter.create_histogram(
|
|
54
|
+
name="agentkit_runtime_operation_latency",
|
|
55
|
+
description="operation latency",
|
|
56
|
+
unit="s",
|
|
57
|
+
explicit_bucket_boundaries_advisory=_GEN_AI_CLIENT_OPERATION_DURATION_BUCKETS,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def trace_a2a_agent(
|
|
62
|
+
self,
|
|
63
|
+
func: Callable,
|
|
64
|
+
span: Span,
|
|
65
|
+
request: RequestContext,
|
|
66
|
+
result: any,
|
|
67
|
+
exception: Exception,
|
|
68
|
+
) -> None:
|
|
69
|
+
"""Get current span and set required attributes."""
|
|
70
|
+
trace_id = span.get_span_context().trace_id
|
|
71
|
+
span_id = span.get_span_context().span_id
|
|
72
|
+
logger.debug(f"Set attributes for span with trace_id={trace_id}, span_id={span_id}")
|
|
73
|
+
|
|
74
|
+
# ===============================
|
|
75
|
+
# Set attributes for current span
|
|
76
|
+
# ===============================
|
|
77
|
+
|
|
78
|
+
span.set_attribute(key="gen_ai.system", value="agentkit")
|
|
79
|
+
|
|
80
|
+
span.set_attribute(key="gen_ai.func_name", value=func.__name__)
|
|
81
|
+
|
|
82
|
+
# TODO: get user_id and session_id, output from event queue
|
|
83
|
+
session_id = request.context_id
|
|
84
|
+
if session_id:
|
|
85
|
+
span.set_attribute(key="gen_ai.session.id", value=session_id)
|
|
86
|
+
user_id = _get_user_id(request)
|
|
87
|
+
if user_id:
|
|
88
|
+
span.set_attribute(key="gen_ai.user.id", value=user_id)
|
|
89
|
+
|
|
90
|
+
span.set_attribute(key="gen_ai.input", value=safe_serialize_to_json_string(request.message.parts))
|
|
91
|
+
|
|
92
|
+
span.set_attribute(key="gen_ai.span.kind", value="a2a_agent")
|
|
93
|
+
span.set_attribute(key="gen_ai.operation.name", value="invoke_agent")
|
|
94
|
+
span.set_attribute(key="gen_ai.operation.type", value="a2a_agent")
|
|
95
|
+
attributes={"gen_ai_operation_name": "invoke_agent", "gen_ai_operation_type": "a2a_agent"}
|
|
96
|
+
|
|
97
|
+
if exception:
|
|
98
|
+
self.handle_exception(span, exception)
|
|
99
|
+
attributes["error_type"] = exception.__class__.__name__
|
|
100
|
+
|
|
101
|
+
# record latency metrics
|
|
102
|
+
if hasattr(span, "start_time") and self.latency_histogram:
|
|
103
|
+
duration = (time.time_ns() - span.start_time) / 1e9 # type: ignore
|
|
104
|
+
self.latency_histogram.record(duration, attributes)
|
|
105
|
+
|
|
106
|
+
@staticmethod
|
|
107
|
+
def handle_exception(span: trace.Span, exception: Exception) -> None:
|
|
108
|
+
status = trace.Status(
|
|
109
|
+
status_code=trace.StatusCode.ERROR,
|
|
110
|
+
# Follow the format in OTEL SDK for description, see:
|
|
111
|
+
# https://github.com/open-telemetry/opentelemetry-python/blob/2b9dcfc5d853d1c10176937a6bcaade54cda1a31/opentelemetry-api/src/opentelemetry/trace/__init__.py#L588 # noqa E501
|
|
112
|
+
description=f"{type(exception).__name__}: {exception}",
|
|
113
|
+
)
|
|
114
|
+
span.set_status(status)
|
|
115
|
+
span.record_exception(exception)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
telemetry = Telemetry()
|
|
119
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from typing import override
|
|
16
|
+
|
|
17
|
+
import uvicorn
|
|
18
|
+
from google.adk.agents.base_agent import BaseAgent
|
|
19
|
+
from google.adk.artifacts.in_memory_artifact_service import (
|
|
20
|
+
InMemoryArtifactService,
|
|
21
|
+
)
|
|
22
|
+
from google.adk.auth.credential_service.in_memory_credential_service import (
|
|
23
|
+
InMemoryCredentialService,
|
|
24
|
+
)
|
|
25
|
+
from google.adk.cli.adk_web_server import AdkWebServer
|
|
26
|
+
from google.adk.cli.utils.base_agent_loader import BaseAgentLoader
|
|
27
|
+
from google.adk.evaluation.local_eval_set_results_manager import (
|
|
28
|
+
LocalEvalSetResultsManager,
|
|
29
|
+
)
|
|
30
|
+
from google.adk.evaluation.local_eval_sets_manager import LocalEvalSetsManager
|
|
31
|
+
from google.adk.memory.in_memory_memory_service import InMemoryMemoryService
|
|
32
|
+
from google.adk.sessions.base_session_service import BaseSessionService
|
|
33
|
+
from veadk import Agent
|
|
34
|
+
from veadk.memory.short_term_memory import ShortTermMemory
|
|
35
|
+
|
|
36
|
+
from agentkit.apps.base_app import BaseAgentkitApp
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class AgentKitAgentLoader(BaseAgentLoader):
|
|
40
|
+
def __init__(self, agent: BaseAgent) -> None:
|
|
41
|
+
super().__init__()
|
|
42
|
+
|
|
43
|
+
self.agent = agent
|
|
44
|
+
|
|
45
|
+
@override
|
|
46
|
+
def load_agent(self, agent_name: str) -> BaseAgent:
|
|
47
|
+
return self.agent
|
|
48
|
+
|
|
49
|
+
@override
|
|
50
|
+
def list_agents(self) -> list[str]:
|
|
51
|
+
return [self.agent.name]
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class AgentkitAgentServerApp(BaseAgentkitApp):
|
|
55
|
+
def __init__(
|
|
56
|
+
self, agent: BaseAgent, short_term_memory: BaseSessionService | ShortTermMemory
|
|
57
|
+
) -> None:
|
|
58
|
+
super().__init__()
|
|
59
|
+
|
|
60
|
+
_artifact_service = InMemoryArtifactService()
|
|
61
|
+
_credential_service = InMemoryCredentialService()
|
|
62
|
+
|
|
63
|
+
_eval_sets_manager = LocalEvalSetsManager(agents_dir=".")
|
|
64
|
+
_eval_set_results_manager = LocalEvalSetResultsManager(agents_dir=".")
|
|
65
|
+
|
|
66
|
+
self.server = AdkWebServer(
|
|
67
|
+
agent_loader=AgentKitAgentLoader(agent),
|
|
68
|
+
session_service=short_term_memory
|
|
69
|
+
if isinstance(short_term_memory, BaseSessionService)
|
|
70
|
+
else short_term_memory.session_service,
|
|
71
|
+
memory_service=agent.long_term_memory
|
|
72
|
+
if isinstance(agent, Agent) and agent.long_term_memory
|
|
73
|
+
else InMemoryMemoryService(),
|
|
74
|
+
artifact_service=_artifact_service,
|
|
75
|
+
credential_service=_credential_service,
|
|
76
|
+
eval_sets_manager=_eval_sets_manager,
|
|
77
|
+
eval_set_results_manager=_eval_set_results_manager,
|
|
78
|
+
agents_dir=".",
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
self.app = self.server.get_fast_api_app()
|
|
82
|
+
|
|
83
|
+
def run(self, host: str, port: int = 8000) -> None:
|
|
84
|
+
"""Run the app with Uvicorn server."""
|
|
85
|
+
uvicorn.run(self.app, host=host, port=port)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from abc import ABC, abstractmethod
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class BaseAgentkitApp(ABC):
|
|
19
|
+
@abstractmethod
|
|
20
|
+
def run(self, **kwargs): ...
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
import inspect
|
|
17
|
+
import logging
|
|
18
|
+
import time
|
|
19
|
+
from functools import wraps
|
|
20
|
+
from typing import Any, Callable, override
|
|
21
|
+
|
|
22
|
+
from fastmcp import FastMCP
|
|
23
|
+
from fastmcp.server.server import Transport
|
|
24
|
+
|
|
25
|
+
from agentkit.apps.base_app import BaseAgentkitApp
|
|
26
|
+
from agentkit.apps.mcp_app.telemetry import telemetry
|
|
27
|
+
|
|
28
|
+
logger = logging.getLogger(__name__)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class AgentkitMCPApp(BaseAgentkitApp):
|
|
32
|
+
def __init__(self) -> None:
|
|
33
|
+
super().__init__()
|
|
34
|
+
|
|
35
|
+
self._mcp_server = FastMCP("agentkit.mcp_server")
|
|
36
|
+
|
|
37
|
+
def tool(self, func: Callable) -> Callable:
|
|
38
|
+
if inspect.iscoroutinefunction(func):
|
|
39
|
+
|
|
40
|
+
@wraps(func)
|
|
41
|
+
async def async_wrapper(*args, **kwargs) -> Any:
|
|
42
|
+
# with tracer.start_as_current_span("tool") as span:
|
|
43
|
+
with telemetry.tracer.start_as_current_span(name="tool") as span:
|
|
44
|
+
exception = None
|
|
45
|
+
try:
|
|
46
|
+
result = await func(*args, **kwargs)
|
|
47
|
+
|
|
48
|
+
except Exception as e:
|
|
49
|
+
logger.error("Invoke tool function failed: %s", e)
|
|
50
|
+
exception = e
|
|
51
|
+
raise e
|
|
52
|
+
finally:
|
|
53
|
+
# handler trace span and metrics
|
|
54
|
+
telemetry.trace_tool(
|
|
55
|
+
func,
|
|
56
|
+
span,
|
|
57
|
+
args,
|
|
58
|
+
func_result=result,
|
|
59
|
+
operation_type="mcp_tool",
|
|
60
|
+
exception=exception,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
return result
|
|
64
|
+
|
|
65
|
+
self._mcp_server.tool(async_wrapper)
|
|
66
|
+
else:
|
|
67
|
+
|
|
68
|
+
@wraps(func)
|
|
69
|
+
def sync_wrapper(*args, **kwargs) -> Any:
|
|
70
|
+
# with tracer.start_as_current_span("tool") as span:
|
|
71
|
+
with telemetry.tracer.start_as_current_span(name="tool") as span:
|
|
72
|
+
exception = None
|
|
73
|
+
try:
|
|
74
|
+
result = func(*args, **kwargs)
|
|
75
|
+
except Exception as e:
|
|
76
|
+
logger.error("Invoke tool function failed: %s", e)
|
|
77
|
+
exception = e
|
|
78
|
+
raise e
|
|
79
|
+
finally:
|
|
80
|
+
telemetry.trace_tool(
|
|
81
|
+
func,
|
|
82
|
+
span,
|
|
83
|
+
args,
|
|
84
|
+
func_result=result,
|
|
85
|
+
operation_type="mcp_tool",
|
|
86
|
+
exception=exception,
|
|
87
|
+
)
|
|
88
|
+
return result
|
|
89
|
+
|
|
90
|
+
self._mcp_server.tool(sync_wrapper)
|
|
91
|
+
|
|
92
|
+
return func
|
|
93
|
+
|
|
94
|
+
def agent_as_a_tool(self, func: Callable) -> Callable:
|
|
95
|
+
if inspect.iscoroutinefunction(func):
|
|
96
|
+
|
|
97
|
+
@wraps(func)
|
|
98
|
+
async def async_wrapper(*args, **kwargs) -> Any:
|
|
99
|
+
with telemetry.tracer.start_as_current_span(name="tool") as span:
|
|
100
|
+
exception = None
|
|
101
|
+
try:
|
|
102
|
+
result = await func(*args, **kwargs)
|
|
103
|
+
except Exception as e:
|
|
104
|
+
logger.error("Invoke tool function failed: %s", e)
|
|
105
|
+
exception = e
|
|
106
|
+
raise e
|
|
107
|
+
finally:
|
|
108
|
+
telemetry.trace_tool(
|
|
109
|
+
func,
|
|
110
|
+
span,
|
|
111
|
+
args=args,
|
|
112
|
+
func_result=result,
|
|
113
|
+
operation_type="agent_mcp_tool",
|
|
114
|
+
exception=exception,
|
|
115
|
+
)
|
|
116
|
+
return result
|
|
117
|
+
|
|
118
|
+
self._mcp_server.tool(async_wrapper)
|
|
119
|
+
else:
|
|
120
|
+
|
|
121
|
+
@wraps(func)
|
|
122
|
+
def sync_wrapper(*args, **kwargs) -> Any:
|
|
123
|
+
with telemetry.tracer.start_as_current_span(name="tool") as span:
|
|
124
|
+
exception = None
|
|
125
|
+
try:
|
|
126
|
+
result = func(*args, **kwargs)
|
|
127
|
+
except Exception as e:
|
|
128
|
+
logger.error("Invoke tool function failed: %s", e)
|
|
129
|
+
exception = e
|
|
130
|
+
raise e
|
|
131
|
+
finally:
|
|
132
|
+
telemetry.trace_tool(
|
|
133
|
+
func,
|
|
134
|
+
span,
|
|
135
|
+
args,
|
|
136
|
+
func_result=result,
|
|
137
|
+
operation_type="agent_mcp_tool",
|
|
138
|
+
exception=exception,
|
|
139
|
+
)
|
|
140
|
+
return result
|
|
141
|
+
|
|
142
|
+
self._mcp_server.tool(sync_wrapper)
|
|
143
|
+
|
|
144
|
+
return func
|
|
145
|
+
|
|
146
|
+
@override
|
|
147
|
+
def run(
|
|
148
|
+
self, host: str, port: int = 8000, transport: Transport = "streamable-http"
|
|
149
|
+
) -> None:
|
|
150
|
+
self._mcp_server.run(host=host, port=port, transport=transport)
|