Skip to main content
Glama

score_hooks_batch

Score many hooks ranked with best, or compare named SETS. Free during beta.

    All-or-nothing charge. Plain: texts (1-25, each 3-300 chars). Self-test (E13):
    compare=true + sets (2-4 named lists, <=25 texts total) INSTEAD of texts -> per-set
    rankings + avg_score + winner + an honest winner_summary (same heuristic scorer
    on every set, never view prediction). Also: platform, tags, verbosity, api_key,
    idempotency_key. Returns {results, best, ...} or {sets, winner, winner_summary, ...}.
    Errors: unauthorized, invalid_request, insufficient_credits, rate_limited.
    

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
setsNoCompare mode input: 2-4 NAMED variant lists, e.g. {"curiosity": ["..."], "contrarian": ["..."]}, each 1-25 texts and <=25 texts across all sets. Requires compare=true and excludes `texts`. Every set is scored by the SAME heuristic scorer, so the winner is a craft comparison, never a view prediction.
tagsNo1-5 lowercase slug tags ([a-z0-9_-], <=40 chars) stamped on this call's usage event so a fleet can attribute spend per campaign. Omit for no tagging. Filter later with get_usage(tag=...) / list_hooks(tag=...).
textsNo1-25 hook lines (3-300 chars each) to score and rank. Use this OR sets, never both: texts is the plain ranked mode, sets is the compare mode. Customer charge is zero during beta.
topicNoWhat the hooks are about, 3-200 chars. Supply it to score these lines the way they were generated: the scorer penalises a line that only echoes its own topic back, and it cannot apply that penalty to a topic it was never told. Omit and the scores are topic-blind, so they will not match the numbers a topic-aware call was charged for.
api_keyNoAPI key for this call. Omit to fall back to the Authorization: Bearer / X-API-Key request header (streamable-HTTP only), then the VHGENGINE_API_KEY env var (the stdio default). No key resolvable -> unauthorized.
compareNoSwitch on compare mode, which requires `sets` and returns per-set rankings + a winner instead of one flat ranking. Leave false for the ordinary texts ranking.
platformNoTarget platform, which selects the length/format conventions the hooks are written and scored against. Defaults to tiktok when omitted.tiktok
verbosityNoHow much of the response envelope to return: minimal (identity, text, score total/source, money, honesty warnings, and any persona/shape), standard (the default, including hook receipts), full (adds per-dimension score numbers, notes, and attribution). A failing phone_test survives minimal; passing phone_test, say_it, and pattern_source are standard/full detail. Shapes the RESPONSE only, never what is generated, persisted, hashed for idempotency, or charged.standard
idempotency_keyNoCaller-chosen replay key (any string, unique per intended effect). A repeat call with the SAME key returns the stored result and is NEVER charged twice; the same key with different arguments is an idempotency_conflict. Omit and every call is a fresh, separately charged operation.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
bestNoPlain mode: the highest-scoring entry.
setsNoCompare mode: per-set rankings and avg_score, keyed by your set names.
winnerNoCompare mode: the winning set name.
resultsNoPlain mode: one scored entry per text, ranked.
replayedNotrue when an idempotency_key replayed a stored result, so nothing was charged again. The credits_charged below is what the ORIGINAL call cost.
request_idNoId of this call. Keep it: get_usage(request_id=...) itemises exactly what it charged, and it identifies the call in a support question.
winner_summaryNoCompare mode: an honest reading of the win. The same heuristic scorer runs on every set, so this is a craft comparison, never a view prediction.
credits_chargedNoCredits this call actually cost.
credits_remainingNoYour balance AFTER this charge.
replayed_at_chargeNotrue when the replay was detected at the charge boundary rather than up front; either way you are billed exactly once.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • changedInput schema / properties / texts / description
      Previous value: -"1-25 hook lines (3-300 chars each) to score and rank. Use this OR sets, never both: texts is the plain ranked mode, sets is the compare mode. 1 credit per text either way."New value: +"1-25 hook lines (3-300 chars each) to score and rank. Use this OR sets, never both: texts is the plain ranked mode, sets is the compare mode. Customer charge is zero during beta."
    • changedOutput schema / description
      Previous value: -"Ranked scores for many hooks, or a per-set comparison. 1 credit per text."New value: +"Ranked scores for many hooks, or a per-set comparison. Free during beta."
  2. Changed1 schema field changed
    • changedInput schema / properties / verbosity / description
      Previous value: -"How much of the response envelope to return: minimal (ids/text/totals only), standard (the default), full (adds per-dimension score attribution and timings). Shapes the RESPONSE only, never what is generated, persisted, hashed for idempotency, or charged."New value: +"How much of the response envelope to return: minimal (identity, text, score total/source, money, honesty warnings, and any persona/shape), standard (the default, including hook receipts), full (adds per-dimension score numbers, notes, and attribution). A failing phone_test survives minimal; passing phone_test, say_it, and pattern_source are standard/full detail. Shapes the RESPONSE only, never what is generated, persisted, hashed for idempotency, or charged."
  3. Changed18 schema fields changed
    • addedInput schema / properties / api_key / description
      Added value: +"API key for this call. Omit to fall back to the Authorization: Bearer / X-API-Key request header (streamable-HTTP only), then the VHGENGINE_API_KEY env var (the stdio default). No key resolvable -> unauthorized."
    • addedInput schema / properties / compare / description
      Added value: +"Switch on compare mode, which requires `sets` and returns per-set rankings + a winner instead of one flat ranking. Leave false for the ordinary texts ranking."
    • addedInput schema / properties / idempotency_key / description
      Added value: +"Caller-chosen replay key (any string, unique per intended effect). A repeat call with the SAME key returns the stored result and is NEVER charged twice; the same key with different arguments is an idempotency_conflict. Omit and every call is a fresh, separately charged operation."
    • addedInput schema / properties / platform / description
      Added value: +"Target platform, which selects the length/format conventions the hooks are written and scored against. Defaults to tiktok when omitted."
    • addedInput schema / properties / sets / description
      Added value: +"Compare mode input: 2-4 NAMED variant lists, e.g. {\"curiosity\": [\"...\"], \"contrarian\": [\"...\"]}, each 1-25 texts and <=25 texts across all sets. Requires compare=true and excludes `texts`. Every set is scored by the SAME heuristic scorer, so the winner is a craft comparison, never a view prediction."
    • changedInput schema / properties / tags / anyOf
      Previous value: -[
      -  {
      -    "items": {
      -      "maxLength": 40,
      -      "minLength": 1,
      -      "pattern": "^[a-z0-9_-]+$",
      -      "type": "string"
      -    },
      -    "maxItems": 5,
      -    "minItems": 1,
      -    "type": "array"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "items": {
      +      "maxLength": 40,
      +      "minLength": 1,
      +      "pattern": "^[a-z0-9_-]+$",
      +      "type": "string"
      +    },
      +    "maxItems": 5,
      +    "type": "array"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • addedInput schema / properties / tags / description
      Added value: +"1-5 lowercase slug tags ([a-z0-9_-], <=40 chars) stamped on this call's usage event so a fleet can attribute spend per campaign. Omit for no tagging. Filter later with get_usage(tag=...) / list_hooks(tag=...)."
    • addedInput schema / properties / tags / items
      Added value: +{
      +  "maxLength": 40,
      +  "minLength": 1,
      +  "pattern": "^[a-z0-9_-]+$",
      +  "type": "string"
      +}
    • addedInput schema / properties / tags / maxItems
      Added value: +5
    • addedInput schema / properties / texts / description
      Added value: +"1-25 hook lines (3-300 chars each) to score and rank. Use this OR sets, never both: texts is the plain ranked mode, sets is the compare mode. 1 credit per text either way."
    • addedInput schema / properties / texts / items
      Added value: +{
      +  "maxLength": 300,
      +  "minLength": 3,
      +  "type": "string"
      +}
    • addedInput schema / properties / texts / maxItems
      Added value: +25
    • addedInput schema / properties / texts / minItems
      Added value: +1
    • addedInput schema / properties / topic
      Added value: +{
      +  "anyOf": [
      +    {
      +      "maxLength": 200,
      +      "minLength": 3,
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "What the hooks are about, 3-200 chars. Supply it to score these lines the way they were generated: the scorer penalises a line that only echoes its own topic back, and it cannot apply that penalty to a topic it was never told. Omit and the scores are topic-blind, so they will not match the numbers a topic-aware call was charged for.",
      +  "maxLength": 200,
      +  "minLength": 3,
      +  "title": "Topic"
      +}
    • addedInput schema / properties / verbosity / description
      Added value: +"How much of the response envelope to return: minimal (ids/text/totals only), standard (the default), full (adds per-dimension score attribution and timings). Shapes the RESPONSE only, never what is generated, persisted, hashed for idempotency, or charged."
    • addedOutput schema / description
      Added value: +"Ranked scores for many hooks, or a per-set comparison. 1 credit per text."
    • addedOutput schema / properties
      Added value: +{
      +  "best": {
      +    "description": "Plain mode: the highest-scoring entry."
      +  },
      +  "credits_charged": {
      +    "description": "Credits this call actually cost.",
      +    "type": [
      +      "number",
      +      "null"
      +    ]
      +  },
      +  "credits_remaining": {
      +    "description": "Your balance AFTER this charge.",
      +    "type": [
      +      "number",
      +      "null"
      +    ]
      +  },
      +  "replayed": {
      +    "description": "true when an idempotency_key replayed a stored result, so nothing was charged again. The credits_charged below is what the ORIGINAL call cost.",
      +    "type": [
      +      "boolean",
      +      "null"
      +    ]
      +  },
      +  "replayed_at_charge": {
      +    "description": "true when the replay was detected at the charge boundary rather than up front; either way you are billed exactly once.",
      +    "type": [
      +      "boolean",
      +      "null"
      +    ]
      +  },
      +  "request_id": {
      +    "description": "Id of this call. Keep it: get_usage(request_id=...) itemises exactly what it charged, and it identifies the call in a support question.",
      +    "type": [
      +      "string",
      +      "null"
      +    ]
      +  },
      +  "results": {
      +    "description": "Plain mode: one scored entry per text, ranked.",
      +    "type": [
      +      "array",
      +      "null"
      +    ]
      +  },
      +  "sets": {
      +    "description": "Compare mode: per-set rankings and avg_score, keyed by your set names.",
      +    "type": [
      +      "object",
      +      "null"
      +    ]
      +  },
      +  "winner": {
      +    "description": "Compare mode: the winning set name.",
      +    "type": [
      +      "string",
      +      "null"
      +    ]
      +  },
      +  "winner_summary": {
      +    "description": "Compare mode: an honest reading of the win. The same heuristic scorer runs on every set, so this is a craft comparison, never a view prediction.",
      +    "type": [
      +      "string",
      +      "null"
      +    ]
      +  }
      +}
    • removedOutput schema / title
      Removed value: -"score_hooks_batchDictOutput"
  4. Changed10 schema fields changed
    • addedInput schema / additionalProperties
      Added value: +false
    • addedInput schema / properties / compare
      Added value: +{
      +  "default": false,
      +  "title": "Compare",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / sets
      Added value: +{
      +  "anyOf": [
      +    {
      +      "additionalProperties": {
      +        "items": {
      +          "maxLength": 300,
      +          "minLength": 3,
      +          "type": "string"
      +        },
      +        "maxItems": 25,
      +        "minItems": 1,
      +        "type": "array"
      +      },
      +      "maxProperties": 4,
      +      "minProperties": 2,
      +      "type": "object"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "title": "Sets"
      +}
    • addedInput schema / properties / texts / anyOf
      Added value: +[
      +  {
      +    "items": {
      +      "maxLength": 300,
      +      "minLength": 3,
      +      "type": "string"
      +    },
      +    "maxItems": 25,
      +    "minItems": 1,
      +    "type": "array"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • addedInput schema / properties / texts / default
      Added value: +null
    • removedInput schema / properties / texts / items
      Removed value: -{
      -  "maxLength": 300,
      -  "minLength": 3,
      -  "type": "string"
      -}
    • removedInput schema / properties / texts / maxItems
      Removed value: -25
    • removedInput schema / properties / texts / minItems
      Removed value: -1
    • removedInput schema / properties / texts / type
      Removed value: -"array"
    • removedInput schema / required
      Removed value: -[
      -  "texts"
      -]
  5. First observed

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description fully shoulders the transparency burden. It discloses all-or-nothing charging, free beta status, the same-heuristic-scorer guarantee ('never view prediction'), honest winner_summary, response shapes for both modes, and possible error types. It also clarifies that verbosity only shapes the response and does not affect generation, persistence, hashing, or charges. This is exemplary for a zero-annotation context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense and front-loaded with the core purpose in the first sentence. It then logically progresses through modes, parameters, return types, and errors. While it is longer than ideal, every clause earns its place given the tool's complexity. The use of compact bullet-like syntax (e.g., 'sets (2-4 named lists, <=25 texts total)') maximizes information density without unnecessary prose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is complete for a tool with 9 parameters, an output schema, and no annotations. It explains both operational modes, parameter interactions, response shapes, billing behavior (all-or-nothing, free beta), and error types. With an output schema also present, the description does not need to detail every return field, but it covers the essential behavioral and mode-level context thoroughly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds some combinatorial context (texts vs sets, compare=true requirement) but the input schema already explains these relationships explicitly. It does not provide additional parameter-level meaning beyond what the schema already offers, so it stays at the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource: 'Score many hooks ranked with `best`, or compare named SETS.' This clearly distinguishes the batch scoring and compare modes from singular score_hook and other siblings. The two modes are explicitly contrasted, making the tool's unique purpose obvious.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use each mode: 'Plain: texts (1-25...) Self-test (E13): compare=true + sets ... INSTEAD of texts.' It clarifies the alternative between texts and sets, but does not explicitly name sibling tools like score_hook or generate_hooks_batch as alternatives, so it falls just short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources