Hey everyone! 👋
Following up on my last update about thread persistence using SqliteSaver, I’ve upgraded the chatbot into a 11-tool agentic engine running on Groq (Llama 3.3 70B) and Streamlit.
If you’ve ever tried binding 10+ custom tools to open-weight LLMs, you’ve probably hit APIError: Failed to call a function or malformed argument streams. Here is how I solved those issues and stabilized the loop:
🛠️ The 11-Tool Ecosystem
- Live APIs & Web: get_weather (OpenWeatherMap), maps_tool (OpenStreetMap), web_search (DuckDuckGo)
- Finance & Computation: get_stock_price, calculator, unit_converter
- Productivity: send_email, calendar_event_manager, get_current_datetime
- Context & Memory: personal_memory_store, search_conversation_history
💡 Key Technical Takeaways
- Strict Pydantic Hardening: Instead of relying on raw docstrings or loose dict types, I attached explicit pydantic.BaseModel schemas to every @tool decorator. This forces Llama 3.3 to emit 100% deterministic JSON arguments.
- Decoupled Execution: Separated function invocation from raw token streaming inside Streamlit to prevent stream-parsing collisions during tool calls.
- Clean Graph State: Kept SQLite state checkpoints isolated so failed execution attempts don't contaminate thread history.
🧪 Multi-Tool Test Prompt
I pushed the agent with a compound request:
"Check current time ➔ get Tokyo weather ➔ convert °C to °F ➔ look up map coordinates ➔ store a note in memory."
All tools executed sequentially in a single turn with live status blocks in the Streamlit UI!
What tool-calling setups are you currently building with LangGraph? Drop your questions or code setup below and I'd be happy to share backend snippets! 👇