agent-runtime-sdk 0.1.0__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.
Files changed (51) hide show
  1. agent_runtime/__init__.py +84 -0
  2. agent_runtime/builder.py +317 -0
  3. agent_runtime/config/__init__.py +29 -0
  4. agent_runtime/config/definitions.py +144 -0
  5. agent_runtime/config/policies.py +63 -0
  6. agent_runtime/config/storage.py +117 -0
  7. agent_runtime/context.py +10 -0
  8. agent_runtime/definitions.py +33 -0
  9. agent_runtime/discovery.py +16 -0
  10. agent_runtime/exceptions.py +74 -0
  11. agent_runtime/mcp/__init__.py +28 -0
  12. agent_runtime/mcp/discovery.py +146 -0
  13. agent_runtime/mcp/metadata.py +68 -0
  14. agent_runtime/mcp/utils.py +52 -0
  15. agent_runtime/model_registry.py +40 -0
  16. agent_runtime/plugins/__init__.py +4 -0
  17. agent_runtime/plugins/base.py +90 -0
  18. agent_runtime/plugins/default.py +19 -0
  19. agent_runtime/plugins/instructions.py +38 -0
  20. agent_runtime/plugins/loader.py +59 -0
  21. agent_runtime/policies.py +15 -0
  22. agent_runtime/runtime.py +110 -0
  23. agent_runtime/runtime_engine/__init__.py +22 -0
  24. agent_runtime/runtime_engine/a2a_bridge.py +190 -0
  25. agent_runtime/runtime_engine/a2a_task_io.py +165 -0
  26. agent_runtime/runtime_engine/agent_build.py +315 -0
  27. agent_runtime/runtime_engine/context.py +469 -0
  28. agent_runtime/runtime_engine/loading.py +170 -0
  29. agent_runtime/runtime_engine/observability.py +154 -0
  30. agent_runtime/runtime_engine/policy_registry.py +98 -0
  31. agent_runtime/runtime_engine/protocol_tools.py +94 -0
  32. agent_runtime/runtime_engine/task_flow.py +897 -0
  33. agent_runtime/runtime_engine/tool_flow.py +332 -0
  34. agent_runtime/sdk_agent.py +548 -0
  35. agent_runtime/server/__init__.py +15 -0
  36. agent_runtime/server/app_factory.py +37 -0
  37. agent_runtime/server/bootstrap.py +48 -0
  38. agent_runtime/server/endpoint_utils.py +37 -0
  39. agent_runtime/server/management.py +107 -0
  40. agent_runtime/smol/__init__.py +4 -0
  41. agent_runtime/smol/agents.py +431 -0
  42. agent_runtime/smol/llm_models.py +212 -0
  43. agent_runtime/smol/memory.py +111 -0
  44. agent_runtime/smol/models.py +69 -0
  45. agent_runtime/standalone.py +57 -0
  46. agent_runtime/storage.py +5 -0
  47. agent_runtime/tools.py +5 -0
  48. agent_runtime_sdk-0.1.0.dist-info/METADATA +125 -0
  49. agent_runtime_sdk-0.1.0.dist-info/RECORD +51 -0
  50. agent_runtime_sdk-0.1.0.dist-info/WHEEL +5 -0
  51. agent_runtime_sdk-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,212 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from typing import Any
5
+
6
+ from openai import OpenAI
7
+ from smolagents import ApiModel, ChatMessage, MessageRole, TokenUsage
8
+ from smolagents.models import remove_content_after_stop_sequences
9
+ from smolagents.tools import Tool
10
+
11
+ from .models import (
12
+ OpenAIMessageAssistant,
13
+ OpenAIMessageSystem,
14
+ OpenAIMessageTool,
15
+ OpenAIMessageUser,
16
+ get_tool_json_schema,
17
+ )
18
+
19
+
20
+ class DeepSeekModel(ApiModel):
21
+ """Thin OpenAI-compatible wrapper based on the original agent-side DeepSeek model."""
22
+
23
+ def __init__(
24
+ self,
25
+ model_id: str,
26
+ api_base: str,
27
+ api_key: str | None = None,
28
+ organization: str | None = None,
29
+ project: str | None = None,
30
+ client_kwargs: dict[str, Any] | None = None,
31
+ custom_role_conversions: dict[str, str] | None = None,
32
+ flatten_messages_as_text: bool = False,
33
+ **kwargs,
34
+ ):
35
+ self.client_kwargs = {
36
+ **(client_kwargs or {}),
37
+ "api_key": api_key,
38
+ "base_url": api_base,
39
+ "organization": organization,
40
+ "project": project,
41
+ "timeout": 300,
42
+ }
43
+ super().__init__(
44
+ model_id=model_id,
45
+ custom_role_conversions=custom_role_conversions,
46
+ flatten_messages_as_text=flatten_messages_as_text,
47
+ retry=True,
48
+ **kwargs,
49
+ )
50
+
51
+ def create_client(self):
52
+ return OpenAI(**self.client_kwargs)
53
+
54
+ def generate(
55
+ self,
56
+ messages: list[ChatMessage | dict],
57
+ stop_sequences: list[str] | None = None,
58
+ response_format: dict[str, str] | None = None,
59
+ tools_to_call_from: list[Tool] | None = None,
60
+ **kwargs,
61
+ ) -> ChatMessage:
62
+ completion_kwargs = self._prepare_completion_kwargs(
63
+ messages=messages,
64
+ stop_sequences=stop_sequences,
65
+ response_format=response_format,
66
+ tools_to_call_from=tools_to_call_from,
67
+ model=self.model_id,
68
+ custom_role_conversions=self.custom_role_conversions,
69
+ convert_images_to_image_urls=True,
70
+ **kwargs,
71
+ )
72
+ self._apply_rate_limit()
73
+ response = self.retryer(self.client.chat.completions.create, **completion_kwargs)
74
+ content = response.choices[0].message.content
75
+ if stop_sequences is not None and not self.supports_stop_parameter:
76
+ content = remove_content_after_stop_sequences(content, stop_sequences)
77
+ return ChatMessage(
78
+ role=response.choices[0].message.role,
79
+ content=content,
80
+ tool_calls=response.choices[0].message.tool_calls,
81
+ raw=response,
82
+ token_usage=TokenUsage(
83
+ input_tokens=response.usage.prompt_tokens,
84
+ output_tokens=response.usage.completion_tokens,
85
+ ),
86
+ )
87
+
88
+ def _prepare_completion_kwargs(
89
+ self,
90
+ messages: list[ChatMessage],
91
+ stop_sequences: list[str] | None = None,
92
+ response_format: dict[str, str] | None = None,
93
+ tools_to_call_from: list[Tool] | None = None,
94
+ custom_role_conversions: dict[str, str] | None = None,
95
+ convert_images_to_image_urls: bool = False,
96
+ tool_choice: str | dict | None = "required",
97
+ **kwargs,
98
+ ) -> dict[str, Any]:
99
+ completion_kwargs = {
100
+ "messages": self.chat_messages2deepseek_messages(messages),
101
+ }
102
+
103
+ if stop_sequences is not None and self.supports_stop_parameter:
104
+ completion_kwargs["stop"] = stop_sequences
105
+ if response_format is not None:
106
+ completion_kwargs["response_format"] = response_format
107
+ if tools_to_call_from:
108
+ completion_kwargs["tools"] = [get_tool_json_schema(tool) for tool in tools_to_call_from]
109
+ if tool_choice is not None:
110
+ completion_kwargs["tool_choice"] = tool_choice
111
+
112
+ completion_kwargs.update(kwargs)
113
+ # Keep model-level defaults working the same way as the original agent model.
114
+ completion_kwargs.update(self.kwargs)
115
+ return completion_kwargs
116
+
117
+ @staticmethod
118
+ def chat_messages2deepseek_messages(messages: list[ChatMessage]) -> list[dict[str, Any]]:
119
+ message_list: list[
120
+ OpenAIMessageSystem | OpenAIMessageUser | OpenAIMessageAssistant | OpenAIMessageTool
121
+ ] = []
122
+
123
+ for chat_message in messages:
124
+ match chat_message.role:
125
+ case MessageRole.SYSTEM:
126
+ message_list.append(OpenAIMessageSystem(content=_flatten_text_content(chat_message.content)))
127
+
128
+ case MessageRole.USER:
129
+ message_list.append(OpenAIMessageUser(content=_flatten_text_content(chat_message.content)))
130
+
131
+ case MessageRole.ASSISTANT:
132
+ content = _flatten_text_content(chat_message.content)
133
+ tool_calls = _serialize_tool_calls(chat_message.tool_calls)
134
+ if tool_calls:
135
+ message_list.append(OpenAIMessageAssistant(content=content or "", tool_calls=tool_calls))
136
+ elif content:
137
+ message_list.append(OpenAIMessageAssistant(content=content))
138
+
139
+ case MessageRole.TOOL_CALL:
140
+ tool_calls = _serialize_tool_calls(chat_message.tool_calls)
141
+ if tool_calls:
142
+ message_list.append(OpenAIMessageAssistant(content="", tool_calls=tool_calls))
143
+
144
+ case MessageRole.TOOL_RESPONSE:
145
+ # Prefer an explicit call id in the observation text. If it is missing,
146
+ # fall back to the most recent assistant tool call so OpenAI-compatible
147
+ # servers still accept the tool response.
148
+ tool_call_id = _extract_tool_call_id_from_history(message_list)
149
+ for tool_response in chat_message.content or []:
150
+ if tool_response.get("type") != "text":
151
+ continue
152
+ text = tool_response.get("text", "")
153
+ message_list.append(
154
+ OpenAIMessageTool(
155
+ content=text,
156
+ tool_call_id=_extract_tool_call_id(text) or tool_call_id,
157
+ )
158
+ )
159
+ return [message.to_dict() for message in message_list]
160
+
161
+
162
+ def _flatten_text_content(content: Any) -> str:
163
+ if isinstance(content, str):
164
+ return content
165
+ if isinstance(content, list):
166
+ return "\n".join(item.get("text", "") for item in content if item.get("type") == "text")
167
+ return ""
168
+
169
+
170
+ def _extract_tool_call_id(text: str) -> str:
171
+ prefix = "Call id: "
172
+ if text.startswith(prefix):
173
+ return text.splitlines()[0][len(prefix):].strip()
174
+ return ""
175
+
176
+
177
+ def _extract_tool_call_id_from_history(message_list: list[Any]) -> str:
178
+ if not message_list:
179
+ return ""
180
+ assistant_message = message_list[-1]
181
+ if isinstance(assistant_message, OpenAIMessageAssistant) and assistant_message.tool_calls:
182
+ return assistant_message.tool_calls[-1].get("id", "")
183
+ return ""
184
+
185
+
186
+ def _serialize_tool_calls(tool_calls: Any) -> list[dict[str, Any]]:
187
+ if not isinstance(tool_calls, list):
188
+ return []
189
+
190
+ serialized: list[dict[str, Any]] = []
191
+ for tool_call in tool_calls:
192
+ function = getattr(tool_call, "function", None)
193
+ if function is None:
194
+ continue
195
+ serialized.append(
196
+ {
197
+ "id": getattr(tool_call, "id", ""),
198
+ "type": getattr(tool_call, "type", "function"),
199
+ "function": {
200
+ "name": getattr(function, "name", ""),
201
+ # OpenAI-compatible tool calls require function.arguments to be a string.
202
+ "arguments": _stringify_tool_arguments(getattr(function, "arguments", None)),
203
+ },
204
+ }
205
+ )
206
+ return serialized
207
+
208
+
209
+ def _stringify_tool_arguments(value: Any) -> str:
210
+ if isinstance(value, str):
211
+ return value
212
+ return json.dumps(value, ensure_ascii=False)
@@ -0,0 +1,111 @@
1
+ from __future__ import annotations
2
+
3
+ import inspect
4
+ from collections.abc import Callable
5
+ from dataclasses import dataclass
6
+
7
+ from smolagents import (
8
+ ActionStep as BaseActionStep,
9
+ AgentError,
10
+ ChatMessage,
11
+ ChatMessageToolCall,
12
+ MessageRole,
13
+ )
14
+
15
+ from .models import ChatMessageToolCallFunction
16
+
17
+
18
+ @dataclass
19
+ class ActionStep(BaseActionStep):
20
+ def to_messages(self, summary_mode: bool = False) -> list[ChatMessage]:
21
+ messages = []
22
+ if self.model_output is not None and self.model_output and not summary_mode:
23
+ messages.append(
24
+ ChatMessage(
25
+ role=MessageRole.ASSISTANT,
26
+ content=[{"type": "text", "text": self.model_output.strip()}],
27
+ )
28
+ )
29
+
30
+ if self.tool_calls is not None:
31
+ messages.append(
32
+ ChatMessage(
33
+ role=MessageRole.TOOL_CALL,
34
+ content=[
35
+ {
36
+ "type": "text",
37
+ "text": "Calling tools:\n" + str([tc.dict() for tc in self.tool_calls]),
38
+ }
39
+ ],
40
+ tool_calls=self.tool_call2chat_message_tool_call(),
41
+ )
42
+ )
43
+
44
+ if self.observations_images:
45
+ messages.append(
46
+ ChatMessage(
47
+ role=MessageRole.USER,
48
+ content=[{"type": "image", "image": image} for image in self.observations_images],
49
+ )
50
+ )
51
+
52
+ if self.observations is not None:
53
+ observation_text = f"Observation:\n{self.observations}"
54
+ if self.tool_calls:
55
+ observation_text = f"Call id: {self.tool_calls[0].id}\n" + observation_text
56
+ messages.append(
57
+ ChatMessage(
58
+ role=MessageRole.TOOL_RESPONSE,
59
+ content=[{"type": "text", "text": observation_text}],
60
+ )
61
+ )
62
+
63
+ if self.error is not None:
64
+ error_message = (
65
+ "Error:\n"
66
+ + str(self.error)
67
+ + "\nNow let's retry: take care not to repeat previous errors! "
68
+ + "If you have retried several times, try a completely different approach.\n"
69
+ )
70
+ message_content = f"Call id: {self.tool_calls[0].id}\n" if self.tool_calls else ""
71
+ message_content += error_message
72
+ messages.append(
73
+ ChatMessage(role=MessageRole.TOOL_RESPONSE, content=[{"type": "text", "text": message_content}])
74
+ )
75
+
76
+ return messages
77
+
78
+ def tool_call2chat_message_tool_call(self) -> list[ChatMessageToolCall]:
79
+ chat_message_tool_call_list = []
80
+ for tool_call in self.tool_calls:
81
+ tool_call_dict = tool_call.dict()
82
+ chat_message_tool_call_list.append(
83
+ ChatMessageToolCall(
84
+ id=tool_call_dict.get("id"),
85
+ type=tool_call_dict.get("type"),
86
+ function=ChatMessageToolCallFunction(
87
+ name=tool_call_dict.get("function").get("name"),
88
+ arguments=tool_call_dict.get("function").get("arguments"),
89
+ ),
90
+ )
91
+ )
92
+ return chat_message_tool_call_list
93
+
94
+
95
+ class ToolCallbackRegistry:
96
+ def __init__(self):
97
+ self._callbacks: dict[str, list[Callable]] = {}
98
+
99
+ def register(self, tool_name: str, callback: Callable):
100
+ if tool_name not in self._callbacks:
101
+ self._callbacks[tool_name] = []
102
+ self._callbacks[tool_name].append(callback)
103
+
104
+ def callback(self, chat_message: ChatMessage, **kwargs):
105
+ for tool_call in chat_message.tool_calls or []:
106
+ callbacks = self._callbacks.get(tool_call.function.name, [])
107
+ for callback in callbacks:
108
+ if len(inspect.signature(callback).parameters) == 1:
109
+ callback(chat_message)
110
+ else:
111
+ callback(chat_message, **kwargs)
@@ -0,0 +1,69 @@
1
+ from __future__ import annotations
2
+
3
+ from copy import deepcopy
4
+ from dataclasses import asdict, dataclass
5
+ from typing import Any, Literal
6
+
7
+ from smolagents import Tool
8
+
9
+
10
+ @dataclass
11
+ class OpenAIMessageObject:
12
+ content: str
13
+
14
+ def to_dict(self):
15
+ return asdict(self)
16
+
17
+
18
+ @dataclass
19
+ class OpenAIMessageSystem(OpenAIMessageObject):
20
+ role: Literal["system"] = "system"
21
+
22
+
23
+ @dataclass
24
+ class OpenAIMessageUser(OpenAIMessageObject):
25
+ role: Literal["user"] = "user"
26
+
27
+
28
+ @dataclass
29
+ class OpenAIMessageAssistant(OpenAIMessageObject):
30
+ role: Literal["assistant"] = "assistant"
31
+ tool_calls: list[dict] | None = None
32
+
33
+ def to_dict(self):
34
+ return asdict(self)
35
+
36
+
37
+ @dataclass
38
+ class OpenAIMessageTool(OpenAIMessageObject):
39
+ tool_call_id: str
40
+ role: Literal["tool"] = "tool"
41
+
42
+
43
+ @dataclass
44
+ class ChatMessageToolCallFunction:
45
+ arguments: Any
46
+ name: str
47
+ description: str | None = None
48
+
49
+
50
+ def get_tool_json_schema(tool: Tool) -> dict[str, Any]:
51
+ properties = deepcopy(tool.inputs)
52
+ required: list[str] = []
53
+ for key, value in properties.items():
54
+ if value["type"] == "any":
55
+ value["type"] = "string"
56
+ if not ("nullable" in value and value["nullable"]):
57
+ required.append(key)
58
+ return {
59
+ "type": "function",
60
+ "function": {
61
+ "name": tool.name,
62
+ "description": tool.description,
63
+ "parameters": {
64
+ "type": "object",
65
+ "properties": properties,
66
+ "required": required,
67
+ },
68
+ },
69
+ }
@@ -0,0 +1,57 @@
1
+ from __future__ import annotations
2
+
3
+ """单 agent 模式下的对外启动 facade。"""
4
+
5
+ import logging
6
+ from pathlib import Path
7
+
8
+ from fastapi import FastAPI
9
+ import uvicorn
10
+
11
+ from .server.app_factory import build_app_from_runtime
12
+ from .server.bootstrap import DEFAULT_DEFINITION_PATH, load_single_agent_runtime
13
+ from .server.endpoint_utils import port_from_public_base_url
14
+
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ def build_single_agent_app(
20
+ definition_path: str | Path = DEFAULT_DEFINITION_PATH,
21
+ public_base_url: str | None = None,
22
+ bind_port: int | None = None,
23
+ discoverer=None,
24
+ ) -> FastAPI:
25
+ """从 definition 直接产出一个可运行的 FastAPI 应用。"""
26
+
27
+ runtime = load_single_agent_runtime(
28
+ definition_path=definition_path,
29
+ public_base_url=public_base_url,
30
+ bind_port=bind_port,
31
+ discoverer=discoverer,
32
+ )
33
+ return build_app_from_runtime(runtime, enable_management=False)
34
+
35
+
36
+ def run_single_agent_app(
37
+ app: FastAPI,
38
+ *,
39
+ host: str = "0.0.0.0",
40
+ port: int | None = None,
41
+ ) -> None:
42
+ """按单 agent SDK 的默认约定启动 uvicorn。"""
43
+
44
+ bind_port = port if port is not None else port_from_public_base_url(app.state.runtime.public_url())
45
+ if bind_port is None or bind_port <= 0:
46
+ raise SystemExit(
47
+ "没有可用的默认监听端口;请在 agent_app/agent.yaml 配置带端口的 public_base_url,"
48
+ "或者在 main.py 里调用 run_single_agent_app(app, port=<port>)。"
49
+ )
50
+ logger.info(
51
+ "Starting uvicorn for agent_id=%s host=%s port=%s public_url=%s",
52
+ app.state.runtime.definition.agent.agent_id,
53
+ host,
54
+ bind_port,
55
+ app.state.runtime.public_url(),
56
+ )
57
+ uvicorn.run(app, host=host, port=bind_port)
@@ -0,0 +1,5 @@
1
+ """Public facade for definition storage."""
2
+
3
+ from .config.storage import AgentDefinitionStore
4
+
5
+ __all__ = ["AgentDefinitionStore"]
agent_runtime/tools.py ADDED
@@ -0,0 +1,5 @@
1
+ """对外暴露的运行时协议工具入口。"""
2
+
3
+ from .runtime_engine.protocol_tools import AskAuthTool, AskUserTool, FinalAnswerTool
4
+
5
+ __all__ = ["AskAuthTool", "AskUserTool", "FinalAnswerTool"]
@@ -0,0 +1,125 @@
1
+ Metadata-Version: 2.4
2
+ Name: agent-runtime-sdk
3
+ Version: 0.1.0
4
+ Summary: Single-agent runtime SDK for A2A agents backed by MCP tools.
5
+ Project-URL: Homepage, https://pypi.org/project/agent-runtime-sdk/
6
+ Requires-Python: >=3.11
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: a2a-sdk==0.3.22
9
+ Requires-Dist: smolagents[mcp]
10
+ Requires-Dist: openai
11
+ Requires-Dist: fastapi
12
+ Requires-Dist: uvicorn
13
+ Requires-Dist: httpx
14
+ Requires-Dist: jinja2
15
+ Requires-Dist: pyyaml
16
+ Requires-Dist: loguru
17
+ Requires-Dist: pydantic
18
+ Requires-Dist: rich
19
+ Provides-Extra: observability
20
+ Requires-Dist: langfuse; extra == "observability"
21
+ Requires-Dist: openinference-instrumentation-smolagents; extra == "observability"
22
+ Provides-Extra: dev
23
+ Requires-Dist: build; extra == "dev"
24
+ Requires-Dist: pytest; extra == "dev"
25
+ Requires-Dist: twine; extra == "dev"
26
+
27
+ # agent-runtime-sdk
28
+
29
+ Single-agent runtime SDK for exposing MCP tools as an A2A-compatible agent service.
30
+
31
+ ## Install
32
+
33
+ ```bash
34
+ pip install agent-runtime-sdk
35
+ ```
36
+
37
+ Install optional Langfuse/smolagents observability support:
38
+
39
+ ```bash
40
+ pip install "agent-runtime-sdk[observability]"
41
+ ```
42
+
43
+ ## Basic Usage
44
+
45
+ Create an agent project:
46
+
47
+ ```text
48
+ my-agent/
49
+ ├── agent_app/
50
+ │ ├── agent.yaml
51
+ │ └── plugin.py
52
+ └── main.py
53
+ ```
54
+
55
+ Example `main.py`:
56
+
57
+ ```python
58
+ from pathlib import Path
59
+
60
+ from agent_runtime.standalone import build_single_agent_app, run_single_agent_app
61
+
62
+
63
+ app = build_single_agent_app(
64
+ Path(__file__).resolve().parent / "agent_app" / "agent.yaml"
65
+ )
66
+
67
+
68
+ if __name__ == "__main__":
69
+ run_single_agent_app(app)
70
+ ```
71
+
72
+ Example SDK import:
73
+
74
+ ```python
75
+ from agent_runtime import AgentBuilder
76
+ ```
77
+
78
+ ## Minimal Configuration
79
+
80
+ Example `agent_app/agent.yaml`:
81
+
82
+ ```yaml
83
+ agent:
84
+ agent_id: example-agent
85
+ name: Example Agent
86
+ description: Example A2A agent backed by MCP tools.
87
+
88
+ runtime:
89
+ public_base_url: ${AGENT_PUBLIC_BASE_URL:-http://127.0.0.1:10020}
90
+ model:
91
+ provider: openai_compatible
92
+ api_base: ${MODEL_SOURCE_API_BASE}
93
+ model_id: ${MODEL_SOURCE_MODEL_ID}
94
+ api_key_env: MODEL_SOURCE_API_KEY
95
+
96
+ mcps:
97
+ - name: example
98
+ url: ${MCP_EXAMPLE_URL}
99
+ transport: streamable-http
100
+ ```
101
+
102
+ Run:
103
+
104
+ ```bash
105
+ export MODEL_SOURCE_API_BASE="https://your-model-api.example.com"
106
+ export MODEL_SOURCE_MODEL_ID="your-model-id"
107
+ export MODEL_SOURCE_API_KEY="your-api-key"
108
+ export MCP_EXAMPLE_URL="http://127.0.0.1:8000/mcp"
109
+ export AGENT_PUBLIC_BASE_URL="http://127.0.0.1:10020"
110
+
111
+ python main.py
112
+ ```
113
+
114
+ ## Langfuse
115
+
116
+ After installing `agent-runtime-sdk[observability]`, configure:
117
+
118
+ ```bash
119
+ export MCP_AGENT_LANGFUSE_ENABLED=true
120
+ export LANGFUSE_BASE_URL="http://your-langfuse-host:3000"
121
+ export LANGFUSE_PUBLIC_KEY="pk-lf-..."
122
+ export LANGFUSE_SECRET_KEY="sk-lf-..."
123
+ ```
124
+
125
+ Set `MCP_AGENT_LANGFUSE_ENABLED=false` to disable instrumentation.
@@ -0,0 +1,51 @@
1
+ agent_runtime/__init__.py,sha256=vZfLvJTs7TGfotvY4Mn5yTguQflMX9IbRbQm7W5Sr-U,2155
2
+ agent_runtime/builder.py,sha256=dluDyF5yg9RjUBySHFt782hNA6gtnXHBBoSnBnhe4fM,10541
3
+ agent_runtime/context.py,sha256=5InRJd84fZj03e9I8xdqdlG94TbZICLyP4gy9-uTpXw,250
4
+ agent_runtime/definitions.py,sha256=GGWReUrP2Y-fnojsUb2dxrSH36DQPjtC1vS2j6s9ft0,704
5
+ agent_runtime/discovery.py,sha256=ie76iVQ7XlvqBF1q5UfDG92wuJ-wv9VTCCV6Xan9wSw,386
6
+ agent_runtime/exceptions.py,sha256=NIjRcKM8r-ZnyB3f4wQa4IyeHy-3Fu6QaEBsh3pgNAw,2304
7
+ agent_runtime/model_registry.py,sha256=pzLs3sF4GmEcJea1wKAm1Gt4g3fEMcHIkO6Q2bm2UvI,1008
8
+ agent_runtime/policies.py,sha256=c0Ttz-0Wn1jz8mgmw_YJl4hIUEtBA_teifw_ql1XVhc,295
9
+ agent_runtime/runtime.py,sha256=WMmNmAa5JBKCkjbl7TcLLwNssGdsGfYjYVNAU61fkuA,3721
10
+ agent_runtime/sdk_agent.py,sha256=iUTI66ccgktu9zEgOPCVkQl4N3NT_ld7TNMimFUf7iw,17446
11
+ agent_runtime/standalone.py,sha256=T3NwUJ7Uly-J9zssjB9HvqY6N-ZNThcy45saUE8dB2c,1775
12
+ agent_runtime/storage.py,sha256=ug3oWJefD2fpBtFs7WU_XirW_Jz6AzvrKpv39zNBjM0,130
13
+ agent_runtime/tools.py,sha256=w9rxqjXUNhCQFR2nUeTiGlkpDzJzjc4Baw2NvmbVF4c,199
14
+ agent_runtime/config/__init__.py,sha256=rY1oFQFqqBG0Ih6Mt5TeCUZ9J_bkFSwjxvIokN3FM4g,552
15
+ agent_runtime/config/definitions.py,sha256=i130Ojung9ShVkLKIR2qIgdnDobbNhRFSJUO8tbwy8o,4290
16
+ agent_runtime/config/policies.py,sha256=shhoRQbUlPytOEG0pJCQ_DOkeDxyWi1ECnHA4uZAAGk,1966
17
+ agent_runtime/config/storage.py,sha256=_xjwS1ItHVqtbjOkZnKmZ5dDwfU__5w8ddMKUtSCvVc,4691
18
+ agent_runtime/mcp/__init__.py,sha256=EZSRhs4RxoHXRGSM4nv-4kbSZuAgtGR0VkqIUsyEVFc,721
19
+ agent_runtime/mcp/discovery.py,sha256=nvLTdcdHpMqYrzdL7ymeIcXJclIAoI-buk8senXVnGs,4824
20
+ agent_runtime/mcp/metadata.py,sha256=cGuMJjZWGeqP6Pn5r37uQHhYre_r14aDnGinWVhdew4,2135
21
+ agent_runtime/mcp/utils.py,sha256=ZmaPV2y88XshC71GzBGWY0hpHRLvlW2R-dhZ2QgLSj8,1492
22
+ agent_runtime/plugins/__init__.py,sha256=so756bRTF3SAZ-yrql5hxr3nX2QwWN88MpTzAA1aHE0,200
23
+ agent_runtime/plugins/base.py,sha256=MJuDcH9yJVUGV1CpvaXk0RqWHkmUNNGsbZXRPMbCPJs,2690
24
+ agent_runtime/plugins/default.py,sha256=uXxMqgKLwOqC673zERtE8eW72McxwLUGz64zviSomug,568
25
+ agent_runtime/plugins/instructions.py,sha256=T8f7v7XMlBAY_s_6mDt5HkRC1fevLT9nCRK99eTzo4A,1295
26
+ agent_runtime/plugins/loader.py,sha256=uM9yiK-rIzkU-4LBlXxuDDkh0s9Ci5v0xLE5Nd2kIDY,2131
27
+ agent_runtime/runtime_engine/__init__.py,sha256=OeH5vZG_mHsqcWl0NnYV7A4Wf2Vf5vHdzjo_XtEtNQQ,949
28
+ agent_runtime/runtime_engine/a2a_bridge.py,sha256=Qhq_H9BbqUzmlHOQNWwVl4YaaxrkLiny0QfpPmTA6rk,7089
29
+ agent_runtime/runtime_engine/a2a_task_io.py,sha256=L3BmDPiRgF3yPw49znpRD-6IlPcLe83rRJeJVF3_IwE,5288
30
+ agent_runtime/runtime_engine/agent_build.py,sha256=6IFCqnuha_84hP1nHtw3BiJx_uTVrinPSAU23714Tbw,11146
31
+ agent_runtime/runtime_engine/context.py,sha256=gPG6U208heGO1-vMiaGL52hGUzKffsFSG-BL_hN5ak8,13405
32
+ agent_runtime/runtime_engine/loading.py,sha256=XtmvdabFst1gcaQujG2nhO6UoQfVZU4hoHMJrBaaWkA,5767
33
+ agent_runtime/runtime_engine/observability.py,sha256=L3oI9Y5Zw7ISXT0GMqTHZ-WXdb3hOFaGM1iphUw4gog,4418
34
+ agent_runtime/runtime_engine/policy_registry.py,sha256=Ng7EswD-umdF4XjlVwnZlytwAbjf5ArU5hwSrOnNjSg,3715
35
+ agent_runtime/runtime_engine/protocol_tools.py,sha256=SMtXcoT4JDXrQM0dGXzrXM6Ch8w4aLGRJOdZEv3TGKs,2333
36
+ agent_runtime/runtime_engine/task_flow.py,sha256=94KmcGIlqozfqt0jkinCzyolVOy56JRAfRPv5cRWpo0,28016
37
+ agent_runtime/runtime_engine/tool_flow.py,sha256=pBRwR76WtRDZTR4zOW_ertGZkQNPCdp8w5mOHDikWfc,11352
38
+ agent_runtime/server/__init__.py,sha256=RWGoV_RAB_XoSipKhgK2vurJ22ZrJIALmR8M7wd_XAg,493
39
+ agent_runtime/server/app_factory.py,sha256=AcMIDkIHfGoIhKaqyNTH8dUmUhclPukkPPqUxMT3m9U,1015
40
+ agent_runtime/server/bootstrap.py,sha256=HRs7-XuyUVeqcz3W59S7IO4e3IUjZoUbzDfU3NxlI1s,1582
41
+ agent_runtime/server/endpoint_utils.py,sha256=Y7zi61nFzbFY52IaEN1oWUUs7WEcW018PwK-2IhrSpI,1243
42
+ agent_runtime/server/management.py,sha256=D7p8BKFGG-wYxbQuftjA-0ZyE5rwFV_gTY8rvcdDDQY,3800
43
+ agent_runtime/smol/__init__.py,sha256=WeKTbvwrR8GzdTQsB4h-u35R1lCC1weFdzTvrifyTUc,134
44
+ agent_runtime/smol/agents.py,sha256=rHdGiWGNcyIroKfJEddDts_LEWRJVqtjVnMcjQ4GyRU,16782
45
+ agent_runtime/smol/llm_models.py,sha256=d8xXarHrrkw60GUZCMBF_vtef8qoJjb49WjC9z1d8dI,8172
46
+ agent_runtime/smol/memory.py,sha256=2Cd29kXgqOx51yIHnXdKQhTqeneUn2y8JFDir40UBQM,4057
47
+ agent_runtime/smol/models.py,sha256=0mMMuR50E4Ehs9vFIGliVaWjwKi4ghQTH1pV1uvOz4Y,1548
48
+ agent_runtime_sdk-0.1.0.dist-info/METADATA,sha256=Z73KZZ92m04ySXOqbPi8ndphgf4QBe9f52DbVPhob2k,2760
49
+ agent_runtime_sdk-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
50
+ agent_runtime_sdk-0.1.0.dist-info/top_level.txt,sha256=vDappP7R62mPBfF_Va17SkMnaUilueFJe_Fdyom03jw,14
51
+ agent_runtime_sdk-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ agent_runtime