# What Data Format Do Open-SEO Skills Expect as Input?

> Open-SEO skills require a flat JSON-encoded object with keys matching SKILL.md inputs. Learn how to structure your data for the activate_skill tool.

- Repository: [Every App/open-seo](https://github.com/every-app/open-seo)
- Tags: how-to-guide
- Published: 2026-08-21

---

**Open-SEO skills expect a flat JSON-encoded object with keys matching the required inputs defined in each skill's SKILL.md file, passed through the `activate_skill` tool's args field.**

The `every-app/open-seo` repository exposes reusable SEO capabilities as "skills" through the Model Context Protocol (MCP). When invoking these skills via the internal `activate_skill` interface, you must provide data in a specific JSON structure that aligns with the skill's documented input schema. Understanding the precise input data format for these open-seo skills is essential for successful workflow execution and API integration.

## Input Data Format Structure

Open-SEO skills consume a **flat JSON object** where property names correspond exactly to the *Required inputs* listed in the skill's documentation. The structure follows strict conventions enforced by the runtime validation system.

- **Primitive values** – Strings and numbers for single-value parameters like `projectId` or `market`
- **Simple arrays** – Arrays of strings for multi-value inputs such as `seedTopics` or `keywords`
- **No nesting** – Unless explicitly documented in the SKILL.md, nested objects are not supported
- **Optional omission** – Fields marked as optional can be left out; the skill will use MCP defaults or prompt for clarification

When calling `activate_skill`, you embed this JSON object within the `args` field under the `payload` key. The skill validates the payload internally using Zod schemas defined in `src/types/schemas/*.ts` before executing the defined workflow.

## Required Input Schema

Each skill defines its contract in a dedicated SKILL.md file within the `plugins/openseo/skills/` directory. The property names in your JSON must match these documented fields exactly, including case sensitivity.

For example, the Keyword Research skill at [`plugins/openseo/skills/keyword-research/SKILL.md`](https://github.com/every-app/open-seo/blob/main/plugins/openseo/skills/keyword-research/SKILL.md) specifies `projectId` (string), `seedTopics` (array), and an optional `market` (string). The Link Prospecting skill at [`plugins/openseo/skills/link-prospecting/SKILL.md`](https://github.com/every-app/open-seo/blob/main/plugins/openseo/skills/link-prospecting/SKILL.md) requires `projectId`, `targetDomain`, and `keywords`.

Mismatched keys trigger validation errors in [`src/server/features/sam/SamChatAgent.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/sam/SamChatAgent.ts), which handles the routing and validation of all skill invocations. This agent uses the schemas exposed by [`samSkills.ts`](https://github.com/every-app/open-seo/blob/main/samSkills.ts) to verify incoming requests.

## Practical Code Examples

### Keyword Research Skill

Invoke the keyword-research skill with a payload containing a project identifier and seed topics:

```json
{
  "tool": "activate_skill",
  "args": {
    "name": "keyword-research",
    "payload": {
      "projectId": "proj_01AB23",
      "seedTopics": ["organic coffee", "fair-trade beans"],
      "market": "US"
    }
  }
}

```

The `seedTopics` array accepts multiple strings to seed the research process, while `market` defaults to a predefined value if omitted.

### Link Prospecting Skill

The link-prospecting skill requires a target domain and keyword list:

```json
{
  "tool": "activate_skill",
  "args": {
    "name": "link-prospecting",
    "payload": {
      "projectId": "proj_01AB23",
      "targetDomain": "example.com",
      "keywords": ["coffee roasting", "sustainable packaging"]
    }
  }
}

```

This payload includes the mandatory `targetDomain` string and a `keywords` array for prospecting relevant backlink opportunities.

### TypeScript Client Implementation

When using the TanStack Server Function client, the `activateSkill` method from `@open-seo/sam` serializes the object automatically:

```typescript
import { activateSkill } from "@open-seo/sam";

await activateSkill("keyword-research", {
  projectId: "proj_01AB23",
  seedTopics: ["espresso machines"],
  market: "UK"
});

```

The client library converts the provided object into JSON and forwards it to the `activate_skill` endpoint, handling the wire format transparently.

## Validation and Error Handling

The [`SamChatAgent.ts`](https://github.com/every-app/open-seo/blob/main/SamChatAgent.ts) file in `src/server/features/sam/` validates incoming payloads against the schemas exposed by [`samSkills.ts`](https://github.com/every-app/open-seo/blob/main/samSkills.ts). If you provide data in an unsupported format—such as plain text, CSV, or incorrectly nested objects—the skill rejects the payload with a validation error.

The `list()` and `get(name)` methods in [`samSkills.ts`](https://github.com/every-app/open-seo/blob/main/samSkills.ts) expose the input schemas at runtime, allowing clients to inspect required fields before invocation. This prevents malformed requests from reaching the skill implementations.

## Key Source Files

Understanding the following files clarifies the input expectations:

- **[`plugins/openseo/skills/keyword-research/SKILL.md`](https://github.com/every-app/open-seo/blob/main/plugins/openseo/skills/keyword-research/SKILL.md)** – Documents required inputs (`projectId`, `seedTopics`, `market`) for the keyword research workflow
- **[`plugins/openseo/skills/link-prospecting/SKILL.md`](https://github.com/every-app/open-seo/blob/main/plugins/openseo/skills/link-prospecting/SKILL.md)** – Defines the contract for link prospecting with `targetDomain` and `keywords` requirements
- **[`src/server/features/sam/SamChatAgent.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/sam/SamChatAgent.ts)** – Routes `activate_skill` calls and validates JSON payloads against skill schemas
- **[`src/server/features/sam/samSkills.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/sam/samSkills.ts)** – Provides `list()` and `get()` methods to retrieve skill schemas and metadata
- **`src/types/schemas/*.ts`** – Contains Zod type definitions that enforce JSON structure at runtime

## Summary

- Open-SEO skills require a **flat JSON object** with keys matching the skill's documented required inputs
- Pass the payload through the `activate_skill` tool's `args` field, specifically within the `payload` property
- Reference each skill's **SKILL.md** file in `plugins/openseo/skills/` to determine exact field names and types
- The system validates inputs using Zod schemas in `src/types/schemas/` and rejects non-JSON or malformed data
- Optional fields can be omitted, triggering defaults or user clarification prompts

## Frequently Asked Questions

### Can I send CSV or XML data instead of JSON to open-seo skills?

No. The `activate_skill` tool explicitly expects a JSON-encoded object in the `args.payload` field. Providing CSV, XML, or plain text causes the validation logic in [`SamChatAgent.ts`](https://github.com/every-app/open-seo/blob/main/SamChatAgent.ts) to reject the request with a schema validation error.

### What happens if I omit an optional field in the skill payload?

Optional fields can be safely omitted from the JSON object. According to the source implementation in `every-app/open-seo`, the skill will either apply MCP default values or prompt the user for clarification during workflow execution. Required fields must always be present.

### How do I discover the required input fields for a specific skill?

Query the skill metadata through the [`samSkills.ts`](https://github.com/every-app/open-seo/blob/main/samSkills.ts) module, which exposes `list()` and `get(name)` methods. Alternatively, examine the SKILL.md file located in the skill's directory under `plugins/openseo/skills/{skill-name}/SKILL.md` to view the documented required inputs and their types.

### Are nested objects supported in skill payloads?

Generally no. Unless the specific skill's SKILL.md explicitly documents nested structures, open-seo skills expect a flat object with primitive values or simple arrays. Nested objects will fail Zod schema validation in `src/types/schemas/` unless specifically defined in the skill's input types.