child), a "type" and a "direction". Prefer leaf categories. For each group that clearly belongs to a single category, return one suggestion: - "group_key": echo the group's "key". - "match_field": which field to match on (use the group's field). - "match_operator": "contains" for free-text descriptions, "equals" for clean counterparty names. - "match_token": a short, lowercase, DISTINCTIVE substring that appears VERBATIM in the group's samples (e.g. "mercadona", "netflix"). Never invent text that is not present. Never use a token so generic it would match unrelated transactions (avoid words like "compra", "payment", "card"). - "category_id": the id of the best-fitting existing category. An outflow group must map to a spending category, an inflow group to an income category. - If, and only if, no existing category fits, leave "category_id" empty and instead propose "new_category_name" and "new_category_direction" (inflow or outflow). - "confidence": 0.0–1.0, how sure you are. Aim for broad coverage: return a suggestion for EVERY group you can map to a category with reasonable confidence. Only skip a group when it is genuinely ambiguous — for example internal transfers between the user's own accounts, or a catch-all group mixing unrelated transactions. Never invent a category you are unsure about; instead let "confidence" honestly reflect your certainty (the app filters out low-confidence suggestions itself). PROMPT; } /** * @return array */ public function schema(JsonSchema $schema): array { return [ 'suggestions' => $schema->array()->items( $schema->object(fn (JsonSchema $schema): array => [ 'group_key' => $schema->string()->required(), 'match_field' => $schema->string()->enum(['description', 'creditor_name', 'debtor_name'])->required(), 'match_operator' => $schema->string()->enum(['contains', 'equals'])->required(), 'match_token' => $schema->string()->required(), 'category_id' => $schema->string(), 'new_category_name' => $schema->string(), 'new_category_direction' => $schema->string()->enum(['inflow', 'outflow']), 'confidence' => $schema->number()->required(), ]) )->required(), ]; } }