$npx -y skills add apify/agent-skills --skill apify-generate-output-schemaGenerate output schemas (dataset_schema.json, output_schema.json, key_value_store_schema.json) for an Apify Actor by analyzing its source code. Use when creating or updating Actor output schemas.
| 1 | # Generate Actor output schema |
| 2 | |
| 3 | You are generating output schema files for an Apify Actor. The output schema tells Apify Console how to display run results. You will analyze the Actor's source code, create `dataset_schema.json`, `output_schema.json`, and `key_value_store_schema.json` (if the Actor uses key-value store), and update `actor.json`. |
| 4 | |
| 5 | ## Core principles |
| 6 | |
| 7 | - **Analyze code first**: Read the Actor's source to understand what data it actually pushes to the dataset — never guess |
| 8 | - **Every field is nullable**: APIs and websites are unpredictable — always set `"nullable": true` |
| 9 | - **Anonymize examples**: Never use real user IDs, usernames, or personal data in examples |
| 10 | - **Verify against code**: If TypeScript types exist, cross-check the schema against both the type definition AND the code that produces the values |
| 11 | - **Reuse existing patterns**: Before generating schemas, check if other Actors in the same repository already have output schemas — match their structure, naming conventions, description style, and formatting |
| 12 | - **Don't reinvent the wheel**: Reuse existing type definitions, interfaces, and utilities from the codebase instead of creating duplicate definitions |
| 13 | |
| 14 | --- |
| 15 | |
| 16 | ## Phase 1: Discover Actor structure |
| 17 | |
| 18 | **Goal**: Locate the Actor and understand its output |
| 19 | |
| 20 | Initial request: $ARGUMENTS |
| 21 | |
| 22 | **Actions**: |
| 23 | 1. Create todo list with all phases |
| 24 | 2. Find the `.actor/` directory containing `actor.json` |
| 25 | 3. Read `actor.json` to understand the Actor's configuration |
| 26 | 4. Check if `dataset_schema.json`, `output_schema.json`, and `key_value_store_schema.json` already exist |
| 27 | 5. **Search for existing schemas in the repository**: Look for other `.actor/` directories or schema files (e.g., `**/dataset_schema.json`, `**/output_schema.json`, `**/key_value_store_schema.json`) to learn the repo's conventions — match their description style, field naming, example formatting, and overall structure |
| 28 | 6. Find all places where data is pushed to the dataset: |
| 29 | - **JavaScript/TypeScript**: Search for `Actor.pushData(`, `dataset.pushData(`, `Dataset.pushData(` |
| 30 | - **Python**: Search for `Actor.push_data(`, `dataset.push_data(`, `Dataset.push_data(` |
| 31 | 7. Find all places where data is stored in the key-value store: |
| 32 | - **JavaScript/TypeScript**: Search for `Actor.setValue(`, `keyValueStore.setValue(`, `KeyValueStore.setValue(` |
| 33 | - **Python**: Search for `Actor.set_value(`, `key_value_store.set_value(`, `KeyValueStore.set_value(` |
| 34 | 8. Find output type definitions — **reuse them directly** instead of recreating from scratch: |
| 35 | - **TypeScript**: Look for output type interfaces/types (e.g., in `src/types/`, `src/types/output.ts`). If an interface or type already defines the output shape, derive the schema fields from it — do not create a parallel definition |
| 36 | - **Python**: Look for TypedDict, dataclass, or Pydantic model definitions. Use the existing field names, types, and docstrings as the source of truth |
| 37 | 9. Check for existing shared schema utilities or helper functions in the codebase that handle schema generation or validation — reuse them rather than creating new logic |
| 38 | 10. If inline `storages.dataset` or `storages.keyValueStore` config exists in `actor.json`, note it for migration |
| 39 | |
| 40 | Present findings to user: list all discovered dataset output fields, key-value store keys, their types, and where they come from. |
| 41 | |
| 42 | --- |
| 43 | |
| 44 | ## Phase 2: Generate `dataset_schema.json` |
| 45 | |
| 46 | **Goal**: Create a complete dataset schema with field definitions and display views |
| 47 | |
| 48 | ### File structure |
| 49 | |
| 50 | ```json |
| 51 | { |
| 52 | "actorSpecification": 1, |
| 53 | "fields": { |
| 54 | "$schema": "http://json-schema.org/draft-07/schema#", |
| 55 | "type": "object", |
| 56 | "properties": { |
| 57 | // ALL output fields here — every field the Actor can produce, |
| 58 | // not just the ones shown in the overview view |
| 59 | }, |
| 60 | "required": [], |
| 61 | "additionalProperties": true |
| 62 | }, |
| 63 | "views": { |
| 64 | "overview": { |
| 65 | "title": "Overview", |
| 66 | "description": "Most important fields at a glance", |
| 67 | "transformation": { |
| 68 | "fields": [ |
| 69 | // 8-12 most important field names |
| 70 | ] |
| 71 | }, |
| 72 | "display": { |
| 73 | "component": "table", |
| 74 | "properties": { |
| 75 | // Display config for each overview field |
| 76 | } |
| 77 | } |
| 78 | } |
| 79 | } |
| 80 | } |
| 81 | ``` |
| 82 | |
| 83 | ### Consistency with existing schemas |
| 84 | |
| 85 | If existing output schemas were found in the repository during Phase 1 (step 5), follow their conventions: |
| 86 | - Match the **description writing style** (sentence case vs. lowercase, period vs. no period, etc.) |
| 87 | - Match the **field naming convention** (camelCase vs. snake_case) — this must also match the actual keys produced by the Actor cod |