agentic-blocks 0.1.7__py3-none-any.whl → 0.1.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentic-blocks
3
- Version: 0.1.7
3
+ Version: 0.1.8
4
4
  Summary: Simple building blocks for agentic AI systems with MCP client and conversation management
5
5
  Author-email: Magnus Bjelkenhed <bjelkenhed@gmail.com>
6
6
  License: MIT
@@ -187,66 +187,119 @@ Or pass the API key directly:
187
187
  response = call_llm(messages, api_key="your_api_key_here")
188
188
  ```
189
189
 
190
- ## Complete Example - Agent with MCP Tools and LLM
190
+ ## Complete Example - Tool Calling with Weather API
191
+
192
+ This example demonstrates a complete workflow using function calling with an LLM. For a full interactive notebook version, see `notebooks/agentic_example.ipynb`.
191
193
 
192
194
  ```python
193
- from agentic_blocks import MCPClient, Messages, call_llm
194
-
195
- def simple_agent():
196
- # Initialize MCP client and conversation
197
- client = MCPClient("https://example.com/mcp/server/sse")
198
- messages = Messages(
199
- system_prompt="You are a helpful research assistant.",
200
- add_date_and_time=True
201
- )
202
-
203
- # Get available tools
204
- tools = client.list_tools()
205
- print(f"Connected to MCP server with {len(tools)} tools")
206
-
207
- # Simulate user query
208
- user_query = "What's the latest news about AI?"
209
- messages.add_user_message(user_query)
210
-
211
- # Agent decides to use a search tool
212
- if tools:
213
- search_tool = next((t for t in tools if "search" in t["function"]["name"]), None)
214
- if search_tool:
215
- # Add tool call to messages
216
- tool_call = {
217
- "id": "search_001",
218
- "type": "function",
219
- "function": {
220
- "name": search_tool["function"]["name"],
221
- "arguments": '{"query": "latest AI news"}'
222
- }
195
+ from agentic_blocks import call_llm, Messages
196
+
197
+ # Define tools in OpenAI function calling format
198
+ tools = [
199
+ {
200
+ "type": "function",
201
+ "function": {
202
+ "name": "get_weather",
203
+ "description": "Get current weather information for a location",
204
+ "parameters": {
205
+ "type": "object",
206
+ "properties": {
207
+ "location": {
208
+ "type": "string",
209
+ "description": "The city and state, e.g. San Francisco, CA"
210
+ },
211
+ "unit": {
212
+ "type": "string",
213
+ "enum": ["celsius", "fahrenheit"],
214
+ "description": "Temperature unit"
215
+ }
216
+ },
217
+ "required": ["location"]
223
218
  }
224
- messages.add_tool_call(tool_call)
225
-
226
- # Execute the tool
227
- result = client.call_tool(
228
- search_tool["function"]["name"],
229
- {"query": "latest AI news"}
230
- )
231
-
232
- # Add tool response
233
- if result["content"]:
234
- response_text = result["content"][0]["text"]
235
- messages.add_tool_response("search_001", response_text)
236
-
237
- # Use LLM to generate response based on search results
238
- messages.add_user_message("Based on the search results, please summarize the key AI news.")
239
- llm_response = call_llm(messages, temperature=0.7)
240
- messages.add_assistant_message(llm_response)
241
-
242
- # Print conversation
243
- print("\\nConversation:")
244
- print(messages)
245
-
246
- return messages.get_messages()
219
+ }
220
+ },
221
+ {
222
+ "type": "function",
223
+ "function": {
224
+ "name": "calculate",
225
+ "description": "Perform a mathematical calculation",
226
+ "parameters": {
227
+ "type": "object",
228
+ "properties": {
229
+ "expression": {
230
+ "type": "string",
231
+ "description": "Mathematical expression to evaluate"
232
+ }
233
+ },
234
+ "required": ["expression"]
235
+ }
236
+ }
237
+ }
238
+ ]
239
+
240
+ # Create conversation with system and user prompts
241
+ messages = Messages(
242
+ system_prompt="You are a helpful assistant with access to weather and calculation tools.",
243
+ user_prompt="What is the weather in Stockholm?"
244
+ )
245
+
246
+ # Call LLM with tools - it will decide which tools to call
247
+ model = "gpt-4o-mini" # or your preferred model
248
+ response = call_llm(model=model, messages=messages, tools=tools)
249
+
250
+ # Add the LLM's response (including any tool calls) to conversation
251
+ messages.add_response_message(response)
247
252
 
248
- if __name__ == "__main__":
249
- simple_agent()
253
+ # Display the conversation so far
254
+ for message in messages.get_messages():
255
+ print(message)
256
+
257
+ # Check if there are pending tool calls that need execution
258
+ print("Has pending tool calls:", messages.has_pending_tool_calls())
259
+
260
+ # In a real implementation, you would:
261
+ # 1. Execute the actual tool calls (get_weather, calculate, etc.)
262
+ # 2. Add tool responses using messages.add_tool_response()
263
+ # 3. Call the LLM again to get the final user-facing response
264
+ ```
265
+
266
+ **Expected Output:**
267
+ ```
268
+ {'role': 'system', 'content': 'You are a helpful assistant with access to weather and calculation tools.'}
269
+ {'role': 'user', 'content': 'What is the weather in Stockholm?'}
270
+ {'role': 'assistant', 'content': '', 'tool_calls': [{'id': 'call_abc123', 'type': 'function', 'function': {'name': 'get_weather', 'arguments': '{"location": "Stockholm, Sweden", "unit": "celsius"}'}}]}
271
+ Has pending tool calls: True
272
+ ```
273
+
274
+ **Key Features Demonstrated:**
275
+ - **Messages management**: Clean conversation history with system/user prompts
276
+ - **Tool calling**: LLM automatically decides to call the `get_weather` function
277
+ - **Response handling**: `add_response_message()` handles both content and tool calls
278
+ - **Pending detection**: `has_pending_tool_calls()` identifies when tools need execution
279
+
280
+ **Next Steps:**
281
+ After the LLM makes tool calls, you would implement the actual tool functions and continue the conversation:
282
+
283
+ ```python
284
+ # Implement actual weather function
285
+ def get_weather(location, unit="celsius"):
286
+ # Your weather API implementation here
287
+ return f"The weather in {location} is sunny, 22°{unit[0].upper()}"
288
+
289
+ # Execute pending tool calls
290
+ if messages.has_pending_tool_calls():
291
+ last_message = messages.get_messages()[-1]
292
+ for tool_call in last_message.get("tool_calls", []):
293
+ if tool_call["function"]["name"] == "get_weather":
294
+ import json
295
+ args = json.loads(tool_call["function"]["arguments"])
296
+ result = get_weather(**args)
297
+ messages.add_tool_response(tool_call["id"], result)
298
+
299
+ # Get final response from LLM
300
+ final_response = call_llm(model=model, messages=messages)
301
+ messages.add_assistant_message(final_response)
302
+ print(f"Final response: {final_response}")
250
303
  ```
251
304
 
252
305
  ## Development Principles
@@ -284,6 +337,8 @@ Messages(system_prompt=None, user_prompt=None, add_date_and_time=False)
284
337
  - `add_user_message(content: str)`: Add user message
285
338
  - `add_assistant_message(content: str)`: Add assistant message
286
339
  - `add_tool_call(tool_call: Dict)`: Add tool call to assistant message
340
+ - `add_tool_calls(tool_calls)`: Add multiple tool calls from ChatCompletionMessageFunctionToolCall objects
341
+ - `add_response_message(message)`: Add ChatCompletionMessage response to conversation
287
342
  - `add_tool_response(call_id: str, content: str)`: Add tool response
288
343
  - `get_messages() -> List[Dict]`: Get all messages
289
344
  - `has_pending_tool_calls() -> bool`: Check for pending tool calls
@@ -2,8 +2,8 @@ agentic_blocks/__init__.py,sha256=LJy2tzTwX9ZjPw8dqkXOWiude7ZDDIaBIvaLC8U4d_Y,43
2
2
  agentic_blocks/llm.py,sha256=CznQ5iNFz_nQsGqjSmtZbCz1YyL6ha1qvnaoFOwsJtk,4868
3
3
  agentic_blocks/mcp_client.py,sha256=15mIN_Qw0OVNJAvfgO3jVZS4-AU4TtvEQSFDlL9ruqA,9773
4
4
  agentic_blocks/messages.py,sha256=WhZDFYb9afvJH9YcieTvEbPdSOkRcclFkCSiMM-9YjY,9904
5
- agentic_blocks-0.1.7.dist-info/licenses/LICENSE,sha256=r4IcBaAjTv3-yfjXgDPuRD953Qci0Y0nQn5JfHwLyBY,1073
6
- agentic_blocks-0.1.7.dist-info/METADATA,sha256=wQIebdtAorFhdsiVKrLi-M_3C60S7qI1oZ9l2ivlLQs,9445
7
- agentic_blocks-0.1.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
- agentic_blocks-0.1.7.dist-info/top_level.txt,sha256=-1a4RAemqicXLU1rRzw4QHV3KlNeQDNxVs3m2gAT238,15
9
- agentic_blocks-0.1.7.dist-info/RECORD,,
5
+ agentic_blocks-0.1.8.dist-info/licenses/LICENSE,sha256=r4IcBaAjTv3-yfjXgDPuRD953Qci0Y0nQn5JfHwLyBY,1073
6
+ agentic_blocks-0.1.8.dist-info/METADATA,sha256=tVHFAuCPukOxAegfZG8XMrwSOugY4tKwCOkKdFU3kCI,11913
7
+ agentic_blocks-0.1.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
+ agentic_blocks-0.1.8.dist-info/top_level.txt,sha256=-1a4RAemqicXLU1rRzw4QHV3KlNeQDNxVs3m2gAT238,15
9
+ agentic_blocks-0.1.8.dist-info/RECORD,,