Chat Messages Validator
ai.chat_messages_validate
Overview
You send 1 to 1,000 messages with roles SYSTEM, DEVELOPER, USER, ASSISTANT or TOOL. We check empty content, duplicate tool-call ids, orphan TOOL results, unresolved assistant calls and RFC 8259 argumentsJson, under profile GENERIC_V1 only. tokensEstimated is always false — we do not count tokens, moderate content, or call a model. Multimodal parts are recorded as metadata and never fetched.
A tool result with no matching assistant call, or two calls sharing an id, looks like a normal transcript until the next model call fails in a way you cannot replay.
Reliability
Fully deterministic structural checks; no tokenizer and no network. CHAT_MESSAGES_INVALID — trigger: a turn is the wrong shape or a role is missing; retryable: no; next: send closed GENERIC_V1 turns. CHAT_MESSAGE_LIMIT_EXCEEDED — trigger: more than 1,000 messages or a content field above 65,536 characters; retryable: no; next: split the transcript. CHAT_PROFILE_UNSUPPORTED — trigger: profile is not GENERIC_V1; retryable: no; next: send GENERIC_V1 or omit it.
Context footprint
Counts and diagnostics only. Message text is never echoed. A successful call costs 1 execution credit.
When to use it
After you assemble a provider-neutral transcript and before you send it to a model or persist it.
When you need a token count, a moderation verdict, or a live model reply.
Scope
Non-goals
- Does not call a model or apply provider token limits
- Does not moderate or rewrite the transcript
- Does not fetch multimodal assets named in content parts
Properties
Capabilities
Cost & billing
Flat rate per invocation
File handling
How we handle your data
What this means
This skill may receive sensitive content, but it does not target sensitive data and returns only a structured non-sensitive result.
Squillify guarantees
- Runs inside Squillify
- This skill runs inside Squillify.
- Payloads are not sent to an external service by this skill.
- Squillify does not permanently store submitted payloads.
- Telemetry records metadata only, not submitted content.
- Submitted payloads are not used for training.
- Submitted payloads are not reviewed by humans.
- This skill does not target sensitive data.
- The response does not contain submitted content.
Your responsibility
Squillify does not determine whether submitted content is sensitive. Your application is responsible for deciding what data it is allowed to submit. Your application is responsible for securing the response.
Input schema
| Field | Type | Required | Description |
|---|---|---|---|
| messages | array | Yes | Bounded array of 1 through 10001 turns; runtime accepts at most 1000 and never estimates tokens. |
| profile | string | No | GENERIC_V1 only. Omit it for GENERIC_V1. |
Output schema
| Field | Type | Required | Description |
|---|---|---|---|
| valid | boolean | Yes | Whether the transcript has no ERROR diagnostics. |
| profile | string | Yes | Applied profile, always GENERIC_V1 in v1. |
| messageCount | integer | Yes | How many turns were supplied. |
| roleCounts | object | Yes | Closed per-role counts for SYSTEM, DEVELOPER, USER, ASSISTANT and TOOL. |
| toolCallCount | integer | Yes | How many assistant toolCalls entries were declared. |
| tokensEstimated | boolean | Yes | Always false because tokens are not estimated. |
| diagnostics | array | Yes | Bounded array of 0 through 500 closed diagnostics sorted by path, severity and code. |
API contract
POST /v1/executecurl -sS -X POST "$BASE/v1/execute" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{"skillKey":"ai.chat_messages_validate","input":{"messages":[{"role":"USER","content":"Hello"}]}}'import { Squillify } from "@squillify/sdk";
const sq = new Squillify({ apiKey: process.env.SQUILLIFY_API_KEY });
const { output } = await sq.execute("ai.chat_messages_validate", {"messages":[{"role":"SYSTEM","content":"You are a support agent."},{"role":"USER","content":"Where is order NW-1?"},{"toolCalls":[{"name":"lookup_order","argumentsJson":"{\"orderId\":\"NW-1\"}","id":"call_1"}],"content":"Let me look that up.","role":"ASSISTANT"},{"toolCallId":"call_1","content":"{\"status\":\"shipped\"}","role":"TOOL"}]});Errors
| Code | HTTP | Retryable | Description |
|---|---|---|---|
| VALIDATION_ERROR | 400 | No | The request payload failed schema validation. |
| UNAUTHORIZED | 401 | No | Missing or invalid API key. |
| SKILL_NOT_ACCESSIBLE | 403 | No | The API key is not granted access to this skill. |
| SKILL_NOT_AVAILABLE_FOR_PLAN | 403 | No | This skill is not included in your current plan. |
| PLAN_ELIGIBILITY_UNAVAILABLE | 503 | Yes | Plan eligibility could not be decided. Retry after backoff. |
| SKILL_NOT_FOUND | 404 | No | The requested skill or version does not exist. |
| TENANT_RATE_LIMITED | 429 | Yes | Request rate limit exceeded. Retry after backoff. |
| QUOTA_EXCEEDED | 429 | Yes | Plan quota exhausted. Retryable once the quota period resets. |
| EXECUTION_TIMEOUT | 504 | Yes | Execution exceeded the allowed time budget. |
| CHAT_MESSAGES_INVALID | 400 | No | The request payload failed this skill's input validation. |
| CHAT_MESSAGE_LIMIT_EXCEEDED | 429 | No | A size, quota, rate, or time limit was exceeded. |
| CHAT_PROFILE_UNSUPPORTED | 400 | No | The skill does not support the requested variant. |
Other limits
| Limit | Value |
|---|---|
| Recommended inline bytes | 32 KiB |
Limitations
- Does not call a model or apply provider token limits
- Does not moderate or rewrite the transcript
- Does not fetch multimodal assets named in content parts
- Counting tokens or pricing a completion
- Safety moderation
How to call
POST /v1/execute (requires authentication)
{
"skillKey": "ai.chat_messages_validate",
"input": {
"messages": [
{
"role": "SYSTEM",
"content": "You are a support agent."
},
{
"role": "USER",
"content": "Where is order NW-1?"
},
{
"toolCalls": [
{
"name": "lookup_order",
"argumentsJson": "{\"orderId\":\"NW-1\"}",
"id": "call_1"
}
],
"content": "Let me look that up.",
"role": "ASSISTANT"
},
{
"toolCallId": "call_1",
"content": "{\"status\":\"shipped\"}",
"role": "TOOL"
}
]
}
}Examples
Assistant call followed by a matching tool result
{
"messages": [
{
"role": "SYSTEM",
"content": "You are a support agent."
},
{
"role": "USER",
"content": "Where is order NW-1?"
},
{
"toolCalls": [
{
"name": "lookup_order",
"argumentsJson": "{\"orderId\":\"NW-1\"}",
"id": "call_1"
}
],
"content": "Let me look that up.",
"role": "ASSISTANT"
},
{
"toolCallId": "call_1",
"content": "{\"status\":\"shipped\"}",
"role": "TOOL"
}
]
}{
"profile": "GENERIC_V1",
"valid": true,
"toolCallCount": 1,
"messageCount": 4,
"diagnostics": [],
"tokensEstimated": false,
"roleCounts": {
"ASSISTANT": 1,
"TOOL": 1,
"SYSTEM": 1,
"USER": 1,
"DEVELOPER": 0
}
}A TOOL turn with no matching assistant call
{
"messages": [
{
"role": "USER",
"content": "Hello"
},
{
"toolCallId": "missing",
"content": "{}",
"role": "TOOL"
}
]
}{
"profile": "GENERIC_V1",
"valid": false,
"toolCallCount": 0,
"messageCount": 2,
"diagnostics": [
{
"code": "ORPHAN_TOOL_RESULT",
"severity": "ERROR",
"message": "A TOOL turn does not resolve any assistant tool call id.",
"path": "/messages/1/toolCallId",
"source": "squillify",
"details": {}
}
],
"tokensEstimated": false,
"roleCounts": {
"ASSISTANT": 0,
"TOOL": 1,
"SYSTEM": 0,
"USER": 1,
"DEVELOPER": 0
}
}Recommended use cases
- Check an assistant tool call is followed by a matching TOOL turn
- Reject duplicate tool-call ids before you send the transcript on
Avoid for
- Counting tokens or pricing a completion
- Safety moderation
Related skills
Composable with
Safety & privacy
- Runs without calling any external service.
- Your payloads are never stored permanently.
- Telemetry captures metadata only — never your payload contents.
- We never train models on your payloads.
- No human reviews your payloads.