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 1. 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. 2. Decoupled Execution: Separated function invocation from raw token streaming inside Streamlit to prevent stream-parsing collisions during tool calls. 3. 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! 🔗 Try the Live App: https://saad7420-chatbot-based-on-langgraph-app-utzuat.streamlit.app/ 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! 👇