predikit: A thin, typed bridge from scikit-learn models to LLM tool calls
The missing bridge between your ML models and your AI agents. MCP tools use the same Pydantic input validation and model execution as direct invoke() calls.
At a glance
- What is it?
- predikit wraps fitted scikit-learn and XGBoost models as LLM-callable tools, generating JSON schemas from Pydantic models and exposing invoke(), to_openai(), and to_langchain() in one package. It solves a real glue-code problem, but the field-name matching rule is a hard constraint you must plan around.
- Who is it for?
- Adopt predikit if you are already using Pydantic v2 and need to expose several fitted sklearn or XGBoost models to an OpenAI or LangChain agent without hand-writing JSON schemas. Skip it if your models are not sklearn-compatible, if you cannot guarantee that Pydantic field names exactly match training column names, or if you need deep custom validation beyond what Pydantic provides.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 14, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The gap predikit fills
Most ML pipelines end at .predict(). The README makes the pain point explicit: getting a prediction callable by an LLM agent requires hand-written JSON schemas, manual type casting, and per-framework boilerplate for OpenAI or LangChain. predikit positions itself as the layer that removes that glue. It targets teams that have already trained a scikit-learn or XGBoost model and want to expose it as a tool an agent can call with natural-language-derived arguments. The audience is not data scientists doing offline scoring; it is engineers building agentic systems where a model needs to be one of several tools in a function-calling loop. The package does not retrain or wrap models in a new inference engine. It only handles the interface: schema generation, input validation, and output formatting.
How ModelTool turns a model into a tool
The core is ModelTool, which takes a fitted sklearn-compatible estimator, a name, a description, a Pydantic BaseModel for inputs, and an output_name. When you call .invoke(input_dict), the flow is validate, predict, return a dict keyed by output_name. The README shows a price example: invoke({"sqft": 2200}) returns {"price_usd": 370730}. Validation is Pydantic v2, so type errors surface as clear messages rather than silent casts. The same tool can export to OpenAI function schema via .to_openai(), to a LangChain StructuredTool via .to_langchain(), or to a plain Python callable via .to_callable(). The async variant .ainvoke() exists for asyncio runtimes. The design is deliberately small: no custom inference loop, no model serving. The tool is just a wrapper that standardizes the boundary between an LLM's JSON arguments and a model's feature vector.
Field names must match training columns exactly
The most important constraint in the README is the field naming rule. predikit maps inputs to features by name, not position. If the model was trained on a DataFrame with columns ["sqft", "bedrooms"], the Pydantic schema fields must be exactly those names. Renaming to square_footage or beds raises a ValueError at runtime, not at schema definition time. The error message is helpful: it lists the missing model features, the schema fields, and the model's expected features. This rule has a practical consequence: you cannot use friendly, agent-facing field names that differ from your training data. If your training pipeline uses column names like f0, f1, f2, your LLM tool will present those names to the model, which may reduce the agent's ability to reason about the arguments. The README notes that if you trained on a numpy array without feature names, predikit has no names to map against, though the truncated text does not say what happens in that case. You should assume that unnamed arrays are unsupported or require you to supply names yourself.
Ensembles and registries: where the scope broadens
Beyond single tools, predikit offers ToolRegistry and ModelEnsemble. ToolRegistry groups multiple ModelTool instances and exports them as a list of OpenAI schemas or LangChain tools, plus a get() method to retrieve a tool by name. ModelEnsemble runs several tools in parallel and reconciles outputs using one of five strategies: collect, mean, vote, weighted_mean, weighted_vote. The collect strategy merges outputs into one dict and allows different output_names. The mean and vote strategies require all tools to share the same output_name, which is a reasonable constraint but one you must design for. Weighted strategies need a weights list. The ensemble exposes the same invoke, ainvoke, to_openai, and to_langchain interface, so an agent sees a single tool that internally fans out to multiple models. The README also mentions loaders from_mlflow() and from_snowflake() for model registries, but gives no code examples, so the exact behavior of those loaders is not documented in the material. That is a gap: you cannot tell from the README whether they pull a model artifact and its feature names, or just a model object.
Installation and first steps
Installation is a standard pip command. The base package is pip install predikit. Optional extras add support for specific integrations: predikit[xgboost] for XGBoost, predikit[langchain] for LangChain StructuredTool export, predikit[mlflow] for the MLflow registry loader, and predikit[snowflake] for the Snowflake loader. The quick start in the README shows a complete flow: train a LogisticRegression on the iris dataset, define a Pydantic BaseModel with four float fields and descriptions, then wrap the model in ModelTool. The example stops mid-way in the truncated README, but the pattern is clear. The core API table lists the constructor arguments: model, name, description, input_schema, output_name, output_description. You must provide all of these; there is no default schema inference. The Pydantic field descriptions are what the LLM sees, so writing good descriptions is part of the setup cost.
What predikit does not do
The README is honest about the scope, but the limitations are worth spelling out. predikit only works with sklearn-compatible estimators. If your model is a PyTorch or TensorFlow network, or a custom object without a .predict() method, this package will not help. The field-name matching rule is a real failure mode: any mismatch between your Pydantic schema and the training columns raises a runtime error, which means you must keep two sources of truth in sync. There is no mention of handling categorical features, missing values, or feature scaling. If your model expects a preprocessing pipeline, you must wrap that pipeline as the model argument, or predikit will pass raw inputs to a model that may not accept them. The async ainvoke() is mentioned, but the README does not describe how it handles thread safety or whether it offloads to a thread pool. The from_mlflow() and from_snowflake() loaders are listed but not explained, so their error handling and feature-name resolution are unknown. For a package that promises zero boilerplate, the field-name constraint is the one piece of boilerplate you cannot avoid.
Alternatives and where predikit sits
The obvious alternative is writing your own wrapper function and passing it to OpenAI or LangChain directly. That is what predikit claims to replace. The difference is that a hand-written wrapper typically requires you to define a JSON schema manually, cast input types, and write a separate function for each framework. predikit centralizes that: one Pydantic model drives both validation and schema generation. Another alternative is using LangChain's own StructuredTool.from_function, which can take a plain Python function and infer a schema from type hints. The difference is that LangChain does not know about sklearn models, so you would still write the function that calls .predict() and formats the output. predikit removes that step by taking the model directly. A more heavy-duty alternative is a model-serving framework like MLflow's model serving or Ray Serve, which expose models over HTTP but do not generate LLM tool schemas. predikit is lighter: it does not serve requests, it just adapts a model to a tool interface. If you already have a serving layer, predikit can sit on top of it, but it does not replace it.
Maintenance and license considerations
The repository shows recent activity, with releases v0.6.2, v0.6.1, and v0.6.0 in August 2026, and the last push on 2026-08-22. The project is not archived, which suggests active maintenance. The license is MIT, which is permissive: you can use, modify, and distribute the code in commercial products, provided you include the license notice. There is no copyleft obligation, so you can link it into proprietary agent frameworks. The maintenance cost for you is small if you stick to the core API, but you should track releases because the package is at version 0.6.x, which implies the API may still change. The README includes a Roadmap section, though the truncated text does not show its contents. Before adopting, check the changelog between versions to see if the constructor arguments or method names have shifted. The dependency on Pydantic v2 is explicit, so you need that version in your environment. The optional extras mean you only pull in XGBoost or LangChain if you need them, which keeps the base install light.
Editorial conclusion
Adopt predikit if you are already using Pydantic v2 and need to expose several fitted sklearn or XGBoost models to an OpenAI or LangChain agent without hand-writing JSON schemas. Skip it if your models are not sklearn-compatible, if you cannot guarantee that Pydantic field names exactly match training column names, or if you need deep custom validation beyond what Pydantic provides. Before committing, verify that your training pipeline preserves column names, check whether the async ainvoke() path suits your agent runtime, and confirm the MIT license fits your distribution model. The field-name matching rule is the single most likely source of runtime errors, so test it with one model before scaling to an ensemble.
Community notes