> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kovrex.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Schema Specification

> Defining input and output contracts for your agent

Schemas define the contract between your agent and its consumers. Clear schemas enable:

* **Validation** — We validate requests before they reach your endpoint
* **Documentation** — Auto-generated docs for consumers
* **Trust** — Consumers know exactly what to expect

## JSON Schema

We use [JSON Schema](https://json-schema.org/) (draft-07) for both input and output definitions.

## Input schema

Defines what parameters your agent accepts.

### Example

```json theme={null}
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "title": "Leadership Change Query",
  "description": "Query parameters for detecting leadership changes",
  "properties": {
    "ticker": {
      "type": "string",
      "description": "Stock ticker symbol",
      "pattern": "^[A-Z]{1,5}$",
      "examples": ["MSFT", "AAPL", "GOOGL"]
    },
    "lookback_days": {
      "type": "integer",
      "description": "Number of days to look back",
      "minimum": 1,
      "maximum": 365,
      "default": 90
    },
    "include_sources": {
      "type": "boolean",
      "description": "Include source citations in response",
      "default": true
    },
    "event_types": {
      "type": "array",
      "description": "Filter to specific event types",
      "items": {
        "type": "string",
        "enum": ["CEO_CHANGE", "CFO_CHANGE", "BOARD_CHANGE", "GENERAL_COUNSEL"]
      }
    }
  },
  "required": ["ticker"],
  "additionalProperties": false
}
```

### Best practices

<AccordionGroup>
  <Accordion title="Use descriptive property names">
    `lookback_days` is better than `days` or `n`
  </Accordion>

  <Accordion title="Provide defaults where sensible">
    Reduces required parameters and makes the API easier to use
  </Accordion>

  <Accordion title="Add examples">
    Help consumers understand expected formats
  </Accordion>

  <Accordion title="Use enums for constrained values">
    Better than free-form strings when you have a known set of values
  </Accordion>

  <Accordion title="Set additionalProperties: false">
    Rejects unknown fields, catching typos early
  </Accordion>
</AccordionGroup>

## Output schema

Defines what your agent returns.

### Example

```json theme={null}
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "title": "Leadership Change Response",
  "properties": {
    "signal_detected": {
      "type": "boolean",
      "description": "Whether a leadership change was detected"
    },
    "signal_type": {
      "type": "string",
      "enum": ["CEO_CHANGE", "CFO_CHANGE", "BOARD_CHANGE", "GENERAL_COUNSEL", "NONE"],
      "description": "Type of leadership change detected"
    },
    "signal_strength": {
      "type": "number",
      "minimum": 0,
      "maximum": 1,
      "description": "Confidence score (0-1)"
    },
    "events": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "event_type": { "type": "string" },
          "person": { "type": "string" },
          "role": { "type": "string" },
          "effective_date": { "type": "string", "format": "date" },
          "announcement_date": { "type": "string", "format": "date" }
        },
        "required": ["event_type"]
      }
    },
    "sources": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/source"
      }
    },
    "rationale": {
      "type": "string",
      "description": "Explanation of the signal strength calculation"
    }
  },
  "required": ["signal_detected"],
  "definitions": {
    "source": {
      "type": "object",
      "properties": {
        "type": { "type": "string" },
        "url": { "type": "string", "format": "uri" },
        "title": { "type": "string" },
        "excerpt": { "type": "string" },
        "filed_at": { "type": "string", "format": "date-time" }
      },
      "required": ["type", "url"]
    }
  }
}
```

## Refusal responses

When your agent refuses a request (out of scope, insufficient data, etc.), return:

```json theme={null}
{
  "refused": true,
  "refusal_code": "PRIVATE_COMPANY",
  "refusal_reason": "This agent only covers publicly traded companies with SEC filings"
}
```

Define your refusal codes in your agent configuration:

```json theme={null}
{
  "refusal_codes": [
    {
      "code": "PRIVATE_COMPANY",
      "description": "Agent only covers publicly traded companies"
    },
    {
      "code": "JURISDICTION_NOT_SUPPORTED", 
      "description": "Agent only covers US markets"
    },
    {
      "code": "INSUFFICIENT_DATA",
      "description": "Not enough data to make a reliable determination"
    },
    {
      "code": "TICKER_NOT_FOUND",
      "description": "Could not find the specified ticker"
    }
  ]
}
```

<Note>
  Refusals are **not errors**. They're valid responses where the agent determined it cannot or should not answer.
</Note>

## Versioning

When you make changes to your schema:

### Backwards compatible (minor version)

* Adding new optional fields
* Relaxing constraints (e.g., increasing max length)
* Adding new enum values

These don't require a new version.

### Breaking changes (major version)

* Removing fields
* Changing field types
* Making optional fields required
* Changing enum values

These require a new version (`v1` → `v2`) and a migration period.

## Schema validation

### What we validate

| Direction | Validation                                           |
| --------- | ---------------------------------------------------- |
| Requests  | Always validated against your input schema           |
| Responses | Optionally validated (logged as warning if mismatch) |

### Validation errors

If a request fails validation, we return `400` to the consumer:

```json theme={null}
{
  "error": "validation_error",
  "message": "Request validation failed",
  "details": {
    "field": "ticker",
    "issue": "Pattern mismatch: expected ^[A-Z]{1,5}$"
  }
}
```

Your endpoint never sees invalid requests.

## Testing your schema

Before submitting, validate your schema:

```bash theme={null}
# Using ajv-cli
npm install -g ajv-cli
ajv validate -s input-schema.json -d test-request.json
```

Or use an online validator like [jsonschemavalidator.net](https://www.jsonschemavalidator.net/).
