Install
openclaw skills install convert-natural-languageUse when (1) user provides a natural language description and asks to convert it to a structured format (SQL query, JSON object, API request, search query, regex pattern). (2) user wants to take a plain-language instruction and produce a machine-readable command or data schema. (3) user asks to parse or normalize a messy text input into a clean structured format.
openclaw skills install convert-natural-languageThis skill converts natural language input into structured machine-readable formats: SQL queries, JSON objects, API request specifications, search queries, regular expressions, and formal grammar productions. It does NOT just find-replace — it understands intent, extracts entities, resolves ambiguity, and produces semantically equivalent structured output.
Key responsibilities:
date >= NOW() - 7 days)/convert-natural-language --sqlNatural language → SQL query. Converts a plain-language description into a syntactically valid SQL statement (SELECT, INSERT, UPDATE, DELETE). Supports PostgreSQL, MySQL, SQLite, and MongoDB query syntax.
Example: "show me all users who signed up in the last 30 days and have never made a purchase" → SELECT * FROM users WHERE created_at >= NOW() - INTERVAL '30 days' AND id NOT IN (SELECT user_id FROM purchases);
/convert-natural-language --jsonNatural language → JSON object. Converts a description into a structured JSON document. Use when the user describes a data structure or configuration in plain terms.
Example: "a user with name John, email john@example.com, age 30, and optional phone number" → {"name": "John", "email": "john@example.com", "age": 30, "phone": null}
/convert-natural-language --apiNatural language → API request specification. Converts a description into an HTTP API call: method, URL path, query parameters, headers, body.
Example: "get the profile of user ID 123 from the /users endpoint" → GET /users/123 (with auth header)
/convert-natural-language --searchNatural language → search query. Converts a conversational search request into a precise query string for a specific search engine or database full-text search.
Example: "find articles about AI from 2023 that mention GPT and were published in Nature or Science" → AI GPT 2023 site:nature.com OR site:science.com (or WHERE ... for DB)
/convert-natural-language --regexNatural language → Regular expression. Converts a description of a text pattern into a regex pattern with named capture groups.
Example: "a date in the format YYYY-MM-DD, like 2024-01-15" → (?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})
/convert-natural-language --schemaNatural language → JSON Schema or TypeScript interface. Converts a description of a data structure into a formal schema definition.
Example: "an array of order objects, each with order_id (string), amount (number), status (enum: pending/paid/refunded), and optional notes" → TypeScript interface or JSON Schema.
/convert-natural-language --commandNatural language → shell command or CLI command. Converts a description into a valid shell command (bash, zsh) or CLI tool invocation (git, docker, kubectl, etc.).
Example: "show me all docker containers that are stopped" → docker ps -a --filter "status=exited"
Detect target format from user input:
--sql--json or --schema--api--search--regex--commandIf format is still ambiguous, ask: "Should this be converted to SQL, JSON, an API call, a search query, or another format?"
Identify intent components from the input:
Entity extraction patterns:
| Natural language | SQL | JSON | API | Regex |
|---|---|---|---|---|
| "all", "every", "everything" | SELECT * | no filter | no query param | .* |
| "last N days/weeks/months" | WHERE ts >= NOW() - INTERVAL 'N days' | {"gte": "2024-01-01"} | &after=2024-01-01 | \d{4}-\d{2}-\d{2} |
| "never", "no", "without" | WHERE id NOT IN (...) or WHERE field IS NULL | {"exists": false} | &has_field=false | negative lookahead |
| "contains", "includes" | WHERE col LIKE '%text%' | {"contains": "text"} | &q=text | .*text.* |
| "or more", "at least" | WHERE amount >= N | {"gte": N} | &min=N | \d+ |
| "optional", "may have" | field = NULL allowed | {"type": "null"} | omitempty in schema | quantifier ? |
| "one of", "either A or B" | WHERE status IN ('A', 'B') | {"enum": ["A", "B"]} | &status=A,B | `(A |
| "sorted by", "order by" | `ORDER BY field ASC | DESC` | (not applicable) | &sort=field |
Ambiguous time references:
DATE_SUB(CURRENT_DATE, INTERVAL 1 DAY) (2024-01-15)Ambiguous entity references:
Incomplete conditions:
ORDER BY amount DESC or ask for limitSELECT * but ask what fields to returnIf critical information is missing and guessing would produce wrong output, ask before generating:
Cannot generate SQL: "users who bought something" — what table contains purchase records?
Please specify: (a) purchase/orders table name, (b) the link between users and orders tables (e.g., user_id foreign key).
For SQL mode:
* if not specified, or list specific columns)For JSON mode:
json.loads() to confirm valid JSONFor API mode:
For Regex mode:
^ at start, $ at end) if pattern represents a complete matchre.compile() — if fails, report syntax error with positionSQL validation:
# Use sqlparse (if available) to check syntax
import sqlparse
parsed = sqlparse.parse(output)
if not parsed:
report_error("Invalid SQL syntax at character {pos}")
# Check for dangerous operations (DROP, DELETE without WHERE — warn but don't block)
JSON validation:
import json
try:
json.loads(output)
except json.JSONDecodeError as e:
report_error(f"Invalid JSON: {e.msg} at position {e.pos}")
Regex validation:
import re
try:
re.compile(output)
except re.error as e:
report_error(f"Invalid regex: {e.msg} at position {e.pos}")
API validation:
For every conversion, return:
"last 30 days" → WHERE created_at >= NOW() - INTERVAL '30 days'
"never made a purchase" → AND id NOT IN (SELECT user_id FROM purchases)
high: intent clear, entities unambiguous, conditions completemedium: some ambiguity resolved by reasonable defaultlow: significant assumptions made — flag for user review{
"output": "SELECT * FROM users WHERE created_at >= NOW() - INTERVAL '30 days' AND id NOT IN (SELECT user_id FROM purchases);",
"format": "sql",
"dialect": "postgresql",
"confidence": "high",
"explanation": {
"last 30 days": "WHERE created_at >= NOW() - INTERVAL '30 days'",
"never made a purchase": "AND id NOT IN (SELECT user_id FROM purchases)",
"all users": "SELECT * FROM users"
},
"warnings": [],
"assumptions": []
}
--confirm-dml flagSELECT * FROM huge_table without WHERE).*) without flagging as too permissiverm -rf or other destructive operations without explicit confirmationusers table, "order items" → order_items table (snake_case plural)| Criterion | Minimum | Ideal |
|---|---|---|
| Syntax validity | Output passes format parser (SQL parses, JSON valid, regex compiles) | Output passes strict schema validation |
| Semantic equivalence | Intent preserved — action, subject, conditions all captured | Intent preserved + nuanced details (ordering, limits, grouping) |
| Entity resolution | Ambiguous references resolved or flagged | All references resolved with context |
| Handling ambiguity | Flagged with specific question to user | Multiple interpretations offered with pros/cons |
| Time reference handling | Current date in UTC for "today", relative dates calculated | Timezone-aware, user-preferred timezone used |
| Edge case coverage | Handles null/empty/missing fields gracefully | Documents every assumption made |
A good output is syntactically valid, semantically equivalent to the input natural language, includes a clear explanation of how each phrase was interpreted, and flags any areas of ambiguity that required assumptions.
| Scenario | Bad | Good |
|---|---|---|
| Missing table name | Assumes "users" table exists, generates SQL | Reports "Cannot determine which table contains user data — please specify table name (e.g., customers, accounts)" |
| Ambiguous time | Converts "recently" to last 7 days without flagging | Reports "Converted 'recently' to last 7 days — please specify exact date range if this is incorrect" |
| Destructive SQL | Generates DELETE FROM users without WHERE from "delete all users" | Generates DELETE with WHERE from "delete users who never logged in" with confirmation |
| No validation | Returns SQL that fails sqlparse | Validates SQL syntax, reports "Invalid SQL: unexpected token at line 1, position 15" |
| Incomplete NL | Returns partial output without noting what's missing | Reports "Could not generate complete query: missing (a) what to select, (b) which table" |
| Regex too broad | Generates .* for "any characters" (matches everything) | Generates .*? (non-greedy) or more specific pattern with explanation |
| Case sensitivity | Ignores case differences in field names | Preserves case: "UserID" → user_id (snake_case) vs UserID (exact) |
| API method | Converts "get data" to POST without confirming | Infers GET from "get/fetch/retrieve", POST from "create/submit", asks if ambiguous |