agentic-blocks 0.1.14__tar.gz → 0.1.16__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.
- {agentic_blocks-0.1.14/src/agentic_blocks.egg-info → agentic_blocks-0.1.16}/PKG-INFO +1 -1
- {agentic_blocks-0.1.14 → agentic_blocks-0.1.16}/pyproject.toml +1 -1
- {agentic_blocks-0.1.14 → agentic_blocks-0.1.16}/src/agentic_blocks/utils/tools_utils.py +81 -67
- {agentic_blocks-0.1.14 → agentic_blocks-0.1.16/src/agentic_blocks.egg-info}/PKG-INFO +1 -1
- {agentic_blocks-0.1.14 → agentic_blocks-0.1.16}/LICENSE +0 -0
- {agentic_blocks-0.1.14 → agentic_blocks-0.1.16}/README.md +0 -0
- {agentic_blocks-0.1.14 → agentic_blocks-0.1.16}/setup.cfg +0 -0
- {agentic_blocks-0.1.14 → agentic_blocks-0.1.16}/src/agentic_blocks/__init__.py +0 -0
- {agentic_blocks-0.1.14 → agentic_blocks-0.1.16}/src/agentic_blocks/llm.py +0 -0
- {agentic_blocks-0.1.14 → agentic_blocks-0.1.16}/src/agentic_blocks/mcp_client.py +0 -0
- {agentic_blocks-0.1.14 → agentic_blocks-0.1.16}/src/agentic_blocks/messages.py +0 -0
- {agentic_blocks-0.1.14 → agentic_blocks-0.1.16}/src/agentic_blocks.egg-info/SOURCES.txt +0 -0
- {agentic_blocks-0.1.14 → agentic_blocks-0.1.16}/src/agentic_blocks.egg-info/dependency_links.txt +0 -0
- {agentic_blocks-0.1.14 → agentic_blocks-0.1.16}/src/agentic_blocks.egg-info/requires.txt +0 -0
- {agentic_blocks-0.1.14 → agentic_blocks-0.1.16}/src/agentic_blocks.egg-info/top_level.txt +0 -0
@@ -14,7 +14,7 @@ agentic_blocks = []
|
|
14
14
|
|
15
15
|
[project]
|
16
16
|
name = "agentic-blocks"
|
17
|
-
version = "0.1.
|
17
|
+
version = "0.1.16"
|
18
18
|
description = "Simple building blocks for agentic AI systems with MCP client and conversation management"
|
19
19
|
readme = "README.md"
|
20
20
|
requires-python = ">=3.11"
|
@@ -2,22 +2,23 @@
|
|
2
2
|
Utilities for working with tools across different formats.
|
3
3
|
"""
|
4
4
|
|
5
|
+
import json
|
5
6
|
from typing import Dict, Any, List
|
6
7
|
|
7
8
|
|
8
9
|
def langchain_tool_to_openai_format(tool) -> Dict[str, Any]:
|
9
10
|
"""
|
10
11
|
Convert a LangChain StructuredTool to OpenAI function calling format.
|
11
|
-
|
12
|
+
|
12
13
|
Args:
|
13
14
|
tool: A langchain_core.tools.structured.StructuredTool instance
|
14
|
-
|
15
|
+
|
15
16
|
Returns:
|
16
|
-
Dictionary in OpenAI function calling format, compatible with
|
17
|
+
Dictionary in OpenAI function calling format, compatible with
|
17
18
|
MCPClient.list_tools() output and call_llm() tools parameter
|
18
19
|
"""
|
19
20
|
schema = tool.args_schema.model_json_schema()
|
20
|
-
|
21
|
+
|
21
22
|
# Resolve $ref references by flattening $defs into the schema
|
22
23
|
# OpenAI doesn't support $ref/$defs, so we need to inline all definitions
|
23
24
|
def resolve_refs(obj, defs):
|
@@ -38,39 +39,39 @@ def langchain_tool_to_openai_format(tool) -> Dict[str, Any]:
|
|
38
39
|
return [resolve_refs(item, defs) for item in obj]
|
39
40
|
else:
|
40
41
|
return obj
|
41
|
-
|
42
|
+
|
42
43
|
# Get definitions for reference resolution
|
43
44
|
defs = schema.get("$defs", {})
|
44
|
-
|
45
|
+
|
45
46
|
# Resolve references in properties
|
46
47
|
resolved_properties = resolve_refs(schema.get("properties", {}), defs)
|
47
|
-
|
48
|
+
|
48
49
|
# Build parameters object without $defs
|
49
50
|
parameters = {
|
50
51
|
"type": "object",
|
51
52
|
"properties": resolved_properties,
|
52
|
-
"required": schema.get("required", [])
|
53
|
+
"required": schema.get("required", []),
|
53
54
|
}
|
54
|
-
|
55
|
+
|
55
56
|
return {
|
56
57
|
"type": "function",
|
57
58
|
"function": {
|
58
59
|
"name": schema.get("title", tool.name),
|
59
60
|
"description": tool.description or schema.get("description", ""),
|
60
|
-
"parameters": parameters
|
61
|
-
}
|
61
|
+
"parameters": parameters,
|
62
|
+
},
|
62
63
|
}
|
63
64
|
|
64
65
|
|
65
66
|
def langchain_tools_to_openai_format(tools: List) -> List[Dict[str, Any]]:
|
66
67
|
"""
|
67
68
|
Convert a list of LangChain StructuredTools to OpenAI function calling format.
|
68
|
-
|
69
|
+
|
69
70
|
Args:
|
70
71
|
tools: List of langchain_core.tools.structured.StructuredTool instances
|
71
|
-
|
72
|
+
|
72
73
|
Returns:
|
73
|
-
List of dictionaries in OpenAI function calling format, compatible with
|
74
|
+
List of dictionaries in OpenAI function calling format, compatible with
|
74
75
|
MCPClient.list_tools() output and call_llm() tools parameter
|
75
76
|
"""
|
76
77
|
return [langchain_tool_to_openai_format(tool) for tool in tools]
|
@@ -79,128 +80,141 @@ def langchain_tools_to_openai_format(tools: List) -> List[Dict[str, Any]]:
|
|
79
80
|
def create_tool_registry(tools: List) -> Dict[str, Any]:
|
80
81
|
"""
|
81
82
|
Create a registry mapping tool names to LangChain tool instances.
|
82
|
-
|
83
|
+
|
83
84
|
Args:
|
84
85
|
tools: List of langchain_core.tools.structured.StructuredTool instances
|
85
|
-
|
86
|
+
|
86
87
|
Returns:
|
87
88
|
Dictionary mapping tool names to tool instances
|
88
89
|
"""
|
89
90
|
return {tool.name: tool for tool in tools}
|
90
91
|
|
91
92
|
|
92
|
-
def execute_tool_call(
|
93
|
+
def execute_tool_call(
|
94
|
+
tool_call: Dict[str, Any], tool_registry: Dict[str, Any]
|
95
|
+
) -> Dict[str, Any]:
|
93
96
|
"""
|
94
97
|
Execute a single tool call using LangChain tool registry.
|
95
|
-
|
98
|
+
|
96
99
|
Args:
|
97
100
|
tool_call: Dictionary with 'tool_name', 'arguments', and 'tool_call_id' keys
|
98
101
|
tool_registry: Registry mapping tool names to tool instances
|
99
|
-
|
102
|
+
|
100
103
|
Returns:
|
101
104
|
Dictionary with 'tool_call_id', 'result', and 'is_error' keys
|
102
105
|
"""
|
103
|
-
tool_name = tool_call.get(
|
104
|
-
arguments = tool_call.get(
|
105
|
-
tool_call_id = tool_call.get(
|
106
|
-
|
106
|
+
tool_name = tool_call.get("tool_name")
|
107
|
+
arguments = tool_call.get("arguments", {})
|
108
|
+
tool_call_id = tool_call.get("tool_call_id")
|
109
|
+
|
107
110
|
try:
|
108
111
|
if tool_name not in tool_registry:
|
109
112
|
raise ValueError(f"Tool '{tool_name}' not found in registry")
|
110
|
-
|
113
|
+
|
111
114
|
tool = tool_registry[tool_name]
|
112
115
|
result = tool.invoke(arguments)
|
113
|
-
|
114
|
-
return {
|
115
|
-
'tool_call_id': tool_call_id,
|
116
|
-
'result': result,
|
117
|
-
'is_error': False
|
118
|
-
}
|
116
|
+
|
117
|
+
return {"tool_call_id": tool_call_id, "result": result, "is_error": False}
|
119
118
|
except Exception as e:
|
120
119
|
return {
|
121
|
-
|
122
|
-
|
123
|
-
|
120
|
+
"tool_call_id": tool_call_id,
|
121
|
+
"result": f"Error executing tool '{tool_name}': {str(e)}",
|
122
|
+
"is_error": True,
|
124
123
|
}
|
125
124
|
|
126
125
|
|
127
|
-
def execute_pending_tool_calls(
|
126
|
+
def execute_pending_tool_calls(
|
127
|
+
messages, tool_registry: Dict[str, Any]
|
128
|
+
) -> List[Dict[str, Any]]:
|
128
129
|
"""
|
129
130
|
Execute all pending tool calls from a Messages instance and add responses back.
|
130
|
-
|
131
|
+
|
131
132
|
Args:
|
132
133
|
messages: Messages instance with pending tool calls
|
133
134
|
tool_registry: Registry mapping tool names to tool instances
|
134
|
-
|
135
|
+
|
135
136
|
Returns:
|
136
137
|
List of execution results compatible with Messages.add_tool_responses format
|
137
138
|
"""
|
138
139
|
pending_tool_calls = messages.get_pending_tool_calls()
|
139
140
|
results = []
|
140
|
-
|
141
|
+
|
141
142
|
for tool_call in pending_tool_calls:
|
142
143
|
result = execute_tool_call(tool_call, tool_registry)
|
143
|
-
|
144
|
+
|
144
145
|
# Convert to format expected by Messages.add_tool_responses
|
145
|
-
if result[
|
146
|
+
if result["is_error"]:
|
146
147
|
tool_response = {
|
147
|
-
|
148
|
-
|
149
|
-
|
148
|
+
"tool_call_id": result["tool_call_id"],
|
149
|
+
"is_error": True,
|
150
|
+
"error": result["result"],
|
150
151
|
}
|
151
152
|
else:
|
152
153
|
tool_response = {
|
153
|
-
|
154
|
-
|
155
|
-
|
154
|
+
"tool_call_id": result["tool_call_id"],
|
155
|
+
"is_error": False,
|
156
|
+
"tool_response": result["result"],
|
156
157
|
}
|
157
|
-
|
158
|
+
|
158
159
|
results.append(tool_response)
|
159
|
-
|
160
|
+
|
160
161
|
# Add tool response back to messages using individual method
|
161
|
-
if result['is_error']:
|
162
|
-
|
163
|
-
else:
|
164
|
-
|
165
|
-
|
162
|
+
# if result['is_error']:
|
163
|
+
# messages.add_tool_response(result['tool_call_id'], result['result'])
|
164
|
+
# else:
|
165
|
+
# messages.add_tool_response(result['tool_call_id'], str(result['result']))
|
166
|
+
|
166
167
|
return results
|
167
168
|
|
168
169
|
|
169
|
-
def execute_and_add_tool_responses(
|
170
|
+
def execute_and_add_tool_responses(
|
171
|
+
messages, tool_registry: Dict[str, Any]
|
172
|
+
) -> List[Dict[str, Any]]:
|
170
173
|
"""
|
171
174
|
Execute all pending tool calls and add them using Messages.add_tool_responses batch method.
|
172
|
-
|
175
|
+
|
173
176
|
Args:
|
174
177
|
messages: Messages instance with pending tool calls
|
175
178
|
tool_registry: Registry mapping tool names to tool instances
|
176
|
-
|
179
|
+
|
177
180
|
Returns:
|
178
181
|
List of execution results compatible with Messages.add_tool_responses format
|
179
182
|
"""
|
180
183
|
pending_tool_calls = messages.get_pending_tool_calls()
|
181
184
|
results = []
|
182
|
-
|
185
|
+
|
183
186
|
for tool_call in pending_tool_calls:
|
184
187
|
result = execute_tool_call(tool_call, tool_registry)
|
185
|
-
|
188
|
+
|
186
189
|
# Convert to format expected by Messages.add_tool_responses
|
187
|
-
if result[
|
190
|
+
if result["is_error"]:
|
188
191
|
tool_response = {
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
+
"tool_call_id": result["tool_call_id"],
|
193
|
+
"is_error": True,
|
194
|
+
"error": result["result"],
|
192
195
|
}
|
193
196
|
else:
|
194
197
|
tool_response = {
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
+
"tool_call_id": result["tool_call_id"],
|
199
|
+
"is_error": False,
|
200
|
+
"tool_response": result["result"],
|
198
201
|
}
|
199
|
-
|
202
|
+
|
200
203
|
results.append(tool_response)
|
201
|
-
|
204
|
+
|
202
205
|
# Add all responses at once using the batch method
|
203
206
|
if results:
|
204
207
|
messages.add_tool_responses(results)
|
208
|
+
|
209
|
+
return results
|
210
|
+
|
211
|
+
|
212
|
+
def print_tool(tool) -> None:
|
213
|
+
"""
|
214
|
+
Print a single LangChain tool in OpenAI format in a readable JSON structure.
|
205
215
|
|
206
|
-
|
216
|
+
Args:
|
217
|
+
tool: A langchain_core.tools.structured.StructuredTool instance
|
218
|
+
"""
|
219
|
+
openai_tool = langchain_tool_to_openai_format(tool)
|
220
|
+
print(json.dumps(openai_tool, indent=2))
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{agentic_blocks-0.1.14 → agentic_blocks-0.1.16}/src/agentic_blocks.egg-info/dependency_links.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|