# KarmaDue with LangChain and LangGraph

The pre-action guard (a `@guarded` decorator that checks with KarmaDue before an install tool runs and obeys `enforce`) lives at [docs/langchain.md](https://karmadue.expo.app/docs/langchain.md). It was tested on 2026-11-12 with langchain-core 1.8.0 and langgraph 1.2.20.

This page adds the second half: **ask KarmaDue first** as a tool, so the model checks for an existing, tested answer before it researches a problem.

Tested: 2026-11-12 with langchain-core 1.8.0 on Python 3.12. The tool builds and its schema is `{'query': string}`. A live `ask` call returns a real answer once `ask` is live on KarmaDue's MCP endpoint (see the changelog). Until then you get KarmaDue's unknown-tool error.

```python
"""'Ask KarmaDue first' as a LangChain tool (pairs with the @guarded decorator in docs/langchain.md)."""
import json, os, requests
from langchain_core.tools import tool

KD_MCP = "https://ogogoizwsfaduzehkshb.supabase.co/functions/v1/mcp"
VIA = os.environ.get("KD_VIA", "recipe-langchain")

@tool
def ask_karmadue(query: str) -> str:
    """Before researching a problem or spinning up agents on it, ask KarmaDue whether it already has a tested,
    checked answer. Input: the problem in plain words. Returns compact answers with sources, or 'Nothing in KD yet.'"""
    r = requests.post(KD_MCP, json={"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "ask", "arguments": {"query": query[:300]}}},
                      headers={"accept": "application/json, text/event-stream", "x-kd-via": VIA}, params={"compact": "1"}, timeout=20)
    res = r.json().get("result") or {}
    return res.get("content", [{}])[0].get("text", json.dumps(r.json())[:500])

if __name__ == "__main__":
    print(ask_karmadue.name, "|", ask_karmadue.args)
    print(ask_karmadue.invoke({"query": "Pillow ANTIALIAS removed resize images"})[:600])
```

Give the model both tools, `ask_karmadue` and your guarded install tools. Add to its instructions: "Before researching an error or a how-to, call ask_karmadue. If it returns answers, try the one with the strongest label first. After you solve something KarmaDue did not know, tell your person; they can add it."

`params={"compact": "1"}` asks for compact MCP results: the same text, without the duplicate `structuredContent`. See [ask.md](https://karmadue.expo.app/docs/ask.md#compact-mode).
