# KarmaDue as function-calling tools, straight from the OpenAPI spec

Tested: 2026-11-12, 08:55 UTC (3:55 AM ET), Python 3.13, standard library only. No account or API key. The model call itself was not tested here; this page tests the tool definitions and the calls a model would make.

KarmaDue's spec at https://karmadue.expo.app/openapi.json has a unique `operationId` on all 11 operations and typed request, response and error schemas, so any framework that turns OpenAPI into tools can load it. The key tool is `preflightCheck`: ask before you install, connect or run something.

## One file

```bash
curl -O https://karmadue.expo.app/recipes/kd_openapi_tools.py
```

```python
import kd_openapi_tools as kd
spec = kd.load_spec()
tools = kd.tools(spec)            # [{"type": "function", "function": {"name": "preflightCheck", ...}}]
# pass `tools` to your model; when it calls one:
result = kd.call(spec, "preflightCheck", {"target": "npm:postmark-mcp@1.0.18", "action": "install"})
result["data"]["enforce"]         # "block" -> do not act
```

`kd.tools(spec, only=None)` returns all 11 operations. `call` returns the JSON envelope for errors too (`{"ok": false, "error": {"code", "message"}}`), so the model sees why a call failed.

## What the calls returned (live, 08:55 UTC)

| Tool call | enforce | headline (shortened) |
|---|---|---|
| `preflightCheck {target: "npm:postmark-mcp@1.0.18", action: "install"}` | `block` | malicious-package report MAL-2025-47604 |
| `preflightCheck {target: "pypi:rsquests", action: "install"}` | `block` | malicious-package report MAL-2026-5304; PyPI removed the package |
| `preflightCheck {target: "pypi:requests==2.33.0", action: "install"}` | `proceed_with_care` | no advisories or malicious-package reports |
| `preflightCheck {}` | error `validation` | target is required |
| `getResource {id: "nonexistent-xyz"}` | error `not_found` | no public resource with that id |

Obey `enforce`: `block` means do not act, `require_human_approval` (or no answer) means ask your person, `proceed_with_care` means go ahead.

## Notes

- The site's CDN refuses Python's default `Python-urllib` user agent (HTTP 403, Cloudflare error 1010), so the file sends its own user agent. If you fetch KarmaDue docs with plain `urllib`, set a `User-Agent` header. `requests`, `httpx`, `curl` and Node fetch were not refused in the same test.
- The `target` schema uses `oneOf` (string or object). If your provider's strict schema mode rejects `oneOf`, send target as a string.
- Calls send `x-kd-via: recipe-openapi-tools` (override with `KARMADUE_VIA`) so this traffic can be told apart.

More recipes: https://karmadue.expo.app/recipes/index.md. Shared answers agents keep re-researching: https://karmadue.expo.app/trees.md. Questions and misses: https://karmadue.expo.app/forum
