Draft Validation
Skill for using LLMs to bootstrap and refine data-validation plans. Instead of writing every check by hand, describe your data and let an LLM generate a starting plan, then iterate with natural language instructions.
Quick start
import pointblank as pb
# Draft a validation plan from data
draft = pb.DraftValidation(
data=df,
model="anthropic:claude-sonnet-4-6",
)
# View the generated code
print(draft.code)
# Check syntax
draft.validate_syntax()
Skill directory structure
skills/draft-validation/
+-- SKILL.md <- This file
+-- references/
+-- providers-reference.md <- LLM provider configuration
When to use what
| I want to... | Use |
|---|---|
| Generate a validation plan from data | DraftValidation |
| Edit an existing plan with instructions | EditValidation |
| Chat interactively about validation | assistant() |
| See what the LLM generated | draft.code |
| Check generated code is valid | draft.validate_syntax() |
| See what changed in an edit | edit.diff() |
| Accept an edit and get a Validate object | edit.accept() |
Core concepts
DraftValidation
Give data to an LLM and get back a validation plan:
draft = pb.DraftValidation(
data=df,
model="anthropic:claude-sonnet-4-6",
api_key=None, # uses env var by default
max_reprompts=1, # retries on invalid code
)
The LLM analyzes the data's columns, types, distributions, and patterns to generate appropriate validation steps.
# The raw LLM response
draft.response
# The extracted Python code
draft.code
# Check if the code is valid Python
draft.validate_syntax() # True/False
# See which steps were generated
draft.changed_steps() # list of step dicts
EditValidation
Modify an existing validation plan with natural language:
# From an existing Validate object
edit = pb.EditValidation(
validation=existing_validation,
instruction="Add a check that order_id is unique and amount is positive",
model="anthropic:claude-sonnet-4-6",
)
# From Python code string
edit = pb.EditValidation(
validation=code_string,
instruction="Remove the regex check and add a between check for age",
model="openai:gpt-4o",
)
# From a YAML file
edit = pb.EditValidation(
validation="validation.yaml",
instruction="Add threshold warnings at 5%",
model="anthropic:claude-sonnet-4-6",
)
Working with edits:
# See the generated code
edit.to_code()
# See what changed
edit.diff()
# See which steps were modified
edit.changed_steps()
# Accept the edit and get a Validate object
validation = edit.accept()
validation.interrogate()
You can supply data to the edit for context:
edit = pb.EditValidation(
validation=existing_validation,
instruction="Add checks for the new columns",
model="anthropic:claude-sonnet-4-6",
data=updated_df,
)
Interactive assistant
Chat with an LLM about data validation:
# Browser-based chat (default)
pb.assistant(
model="anthropic:claude-sonnet-4-6",
data=df,
tbl_name="orders",
)
# Terminal-based chat
pb.assistant(
model="anthropic:claude-sonnet-4-6",
data=df,
display="terminal",
)
The assistant can:
- Suggest validation steps for your data
- Explain Pointblank concepts and methods
- Help debug validation failures
- Generate code snippets
Model string format
All LLM features use the format "provider:model_name":
# Anthropic
model="anthropic:claude-sonnet-4-6"
model="anthropic:claude-haiku-4-5-20251001"
# OpenAI
model="openai:gpt-4o"
model="openai:gpt-4o-mini"
# Ollama (local)
model="ollama:llama3"
model="ollama:mistral"
# AWS Bedrock
model="bedrock:anthropic.claude-sonnet-4-20250514-v1:0"
# Azure OpenAI
model="azure-openai:my-deployment-name"
API key handling
By default, the API key is read from environment variables:
| Provider | Environment variable |
|---|---|
| Anthropic | ANTHROPIC_API_KEY |
| OpenAI | OPENAI_API_KEY |
| Ollama | (no key needed) |
| Bedrock | AWS credentials |
| Azure OpenAI | AZURE_OPENAI_API_KEY |
Or pass explicitly:
draft = pb.DraftValidation(
data=df,
model="anthropic:claude-sonnet-4-6",
api_key="sk-...",
)
Workflows
Bootstrapping validation for a new dataset
- Load your data.
- Run
pb.DraftValidation(data=df, model="..."). - Review the generated code with
draft.code. - Check syntax with
draft.validate_syntax(). - Copy the code into your project and customize.
- Run
interrogate()and iterate.
Iterating on a validation plan
- Start with a draft or existing validation.
- Use
EditValidationwith natural language instructions. - Review changes with
edit.diff(). - Accept with
edit.accept()or iterate with another edit.
Interactive exploration
- Start
pb.assistant(model="...", data=df). - Ask questions about your data and validation needs.
- Copy suggested code into your project.
Gotchas
- LLM output is not guaranteed correct. Always review generated code before using in production.
validate_syntax()checks Python syntax, not semantics. The code may parse but still have incorrect method calls.max_repromptscontrols retries. If the LLM generates invalid code, it will retry up to this many times.- Ollama runs locally. No API key needed but the model must be
downloaded first with
ollama pull. accept()returns an uninterrogated Validate object. Call.interrogate()to execute.- The assistant requires a running display.
"browser"opens a web interface;"terminal"uses the console. Neither works in non-interactive environments. - Large tables may be sampled. The LLM sees a profile/sample of the data, not every row.
Related skills
| Skill | When to use it |
|---|---|
| pointblank | Full Validate workflow after drafting |
| write-validation | Manual validation plan composition |
| scan-and-profile | Profile data before asking the LLM to draft |