# Agent Capability Substitution Resolver (`bono718/agent-capability-substitution-resolver`) Actor

Assess a proposed tool replacement against declared schemas, semantic identifiers, side effects and supplied paired fixtures. Auditable JSON; no tool execution.

- **URL**: https://apify.com/bono718/agent-capability-substitution-resolver.md
- **Developed by:** [Alessandro Bonometti](https://apify.com/bono718) (community)
- **Categories:** AI, Agents, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 substitution assessments

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Agent Capability Substitution Resolver

Can a proposed capability B replace incumbent A for this specific declared task contract?

This tool evaluates a candidate already selected by your router or integration. It does not discover tools, recommend providers, optimize price or execute either service.

### What it checks

- Input compatibility: the candidate must accept every input permitted by the task's supported schema.
- Output guarantees: the candidate's declared output schema must be contained in the task's accepted output schema.
- Goal and output semantic identifiers must match. Identical JSON types alone are insufficient; a positive-sentiment score and a spam score are different meanings.
- Candidate side effects must be explicitly declared and allowed by the task.
- Simple output-field invariants must be established by declared schemas. Passing a few examples does not prove a universal invariant.
- Supplied paired fixtures validate input, both providers' outputs, relevant output equality, invariants and observed effects.
- Optional explicit, lossless, top-level output renaming is assessed as an adapter plan.

All declarations and fixture execution results are supplied by you. The resolver cannot verify that a provider tells the truth about its guarantees or that a fixture actually ran.

### Decisions

- **DROP_IN:** declared supported contracts align, semantic identifiers match, effects are allowed and the minimum supplied paired fixtures pass. `safe_to_substitute` is true only within this declared scope.
- **ADAPTER_REQUIRED:** an explicit lossless output rename makes the contract compatible and fixtures pass. The adapter is not executed or installed; integration testing remains required. `safe_to_substitute` stays false.
- **SHADOW_TEST_REQUIRED:** additional paired fixtures or a candidate runtime invariant guard is needed. Merely adding more examples cannot prove a universal invariant.
- **INSUFFICIENT_EVIDENCE:** semantic identifiers, effects, baseline evidence or supported schema guarantees are missing. Unsupported schema keywords are reported rather than ignored.
- **NOT_SUBSTITUTABLE:** the candidate fails the declared input/output guarantees, semantics, allowed effects or valid paired fixture checks.

When the supplied incumbent baseline is invalid, that fixture cannot establish candidate equivalence.

### Input

On Apify paste the full contract in the **request** JSON field. HTTP takes the contract directly.

`task_contract` contains:

- `goal_id`: caller-defined versioned goal identifier.
- `input_schema`, `output_schema`: supported closed object schemas.
- `output_semantics`: field to caller-defined meaning/unit identifier.
- `allowed_side_effects`: identifiers of permitted effects.
- `invariants`: `{id, field, constraint}`; each constraint uses the supported schema subset.
- `comparison_fields`: exact-value comparisons on paired outputs; must include every required task output.
- `minimum_fixtures`: 1 to 100.

`incumbent_capability` and `candidate_capability` contain:

- `id`, `goal_id`, `input_schema`, `output_schema`, `output_semantics`, `side_effects`.
- `side_effects: []` explicitly declares none; `null` means unknown and cannot pass.

`fixtures` contain unique `id`, `input`, `incumbent_output`, `candidate_output`, `incumbent_side_effects`, `candidate_side_effects`. They are evidence records supplied by the caller, not code to execute.

Optional `output_mapping` maps target task output field to candidate source field. Every candidate output field must be represented exactly once. No coercion, dropped fields, unit conversion or arbitrary transformation is performed.

### Supported schema subset — v0.1

Single `type`: object, array, string, number, integer, boolean or null.

- Objects: explicit properties, required list, `additionalProperties: false`.
- Arrays: items, minItems, maxItems.
- Strings: minLength, maxLength (Unicode codepoints).
- Numbers/integers: minimum, maximum.
- Nonempty enum (up to 100 values).
- title/description are annotations only.

No `$ref`, unions, anyOf/oneOf/allOf, patterns, formats, conditionals, exclusive bounds, arbitrary extensions or open objects. Unsupported features yield INSUFFICIENT_EVIDENCE. Conservative inclusion may reject declarations whose compatibility would require reasoning outside this subset.

Root input/output schemas must be objects. At least one required task output is needed. Exact comparison is object-key order independent and array-order sensitive; missing and null differ. Every task output property, including optional ones, needs matching semantic identifiers.

### Boundaries

- No LLM, network call, provider invocation, fixture execution or production traffic interception.
- No authentication of semantics, side effects, metadata or evidence.
- No general behavioral equivalence proof or production safety certification.
- Finite fixtures cannot establish correctness for all future inputs.
- An adapter result is a reviewable rename specification, not executable deployment.
- Up to 100 fixtures, 100 schema properties per object, 100 invariants, schema depth 8, JSON depth 32 and 64 KiB input.

The synthetic prefilled sentiment fixture uses supplied numbers. It does not call or contain a sentiment model.

### Output

decision, safe_to_substitute, assessment_scope, contract_coverage, compatible_fields, behavioral_gaps, side_effect_differences, unknowns, unsupported_schema_features, fixture_results, adapter_spec, required_tests and limitations.

### Pricing and contact

One result report per evaluation, including negative or insufficient-evidence decisions. Invalid contracts fail before producing a result. Consult the live Pricing tab for current result and startup charges.

bonometti.work.ai@gmail.com

# Actor input Schema

## `request` (type: `object`):

Paste the complete contract. See README for supported schemas, semantic identifiers, effects and fixture requirements.

## Actor input object example

```json
{
  "request": {
    "task_contract": {
      "goal_id": "sentiment-score/v1",
      "input_schema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        },
        "required": [
          "text"
        ],
        "additionalProperties": false
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "score": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        },
        "required": [
          "score"
        ],
        "additionalProperties": false
      },
      "output_semantics": {
        "score": "positive_sentiment_probability/v1"
      },
      "allowed_side_effects": [],
      "invariants": [
        {
          "id": "bounded-score",
          "field": "score",
          "constraint": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        }
      ],
      "comparison_fields": [
        "score"
      ],
      "minimum_fixtures": 2
    },
    "incumbent_capability": {
      "id": "provider-a/v1",
      "goal_id": "sentiment-score/v1",
      "input_schema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        },
        "required": [
          "text"
        ],
        "additionalProperties": false
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "score": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        },
        "required": [
          "score"
        ],
        "additionalProperties": false
      },
      "output_semantics": {
        "score": "positive_sentiment_probability/v1"
      },
      "side_effects": []
    },
    "candidate_capability": {
      "id": "provider-b/v1",
      "goal_id": "sentiment-score/v1",
      "input_schema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        },
        "required": [
          "text"
        ],
        "additionalProperties": false
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "score": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        },
        "required": [
          "score"
        ],
        "additionalProperties": false
      },
      "output_semantics": {
        "score": "positive_sentiment_probability/v1"
      },
      "side_effects": []
    },
    "fixtures": [
      {
        "id": "positive",
        "input": {
          "text": "good"
        },
        "incumbent_output": {
          "score": 0.9
        },
        "candidate_output": {
          "score": 0.9
        },
        "incumbent_side_effects": [],
        "candidate_side_effects": []
      },
      {
        "id": "negative",
        "input": {
          "text": "bad"
        },
        "incumbent_output": {
          "score": 0.1
        },
        "candidate_output": {
          "score": 0.1
        },
        "incumbent_side_effects": [],
        "candidate_side_effects": []
      }
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "request": {
        "task_contract": {
            "goal_id": "sentiment-score/v1",
            "input_schema": {
                "type": "object",
                "properties": {
                    "text": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100
                    }
                },
                "required": [
                    "text"
                ],
                "additionalProperties": false
            },
            "output_schema": {
                "type": "object",
                "properties": {
                    "score": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 1
                    }
                },
                "required": [
                    "score"
                ],
                "additionalProperties": false
            },
            "output_semantics": {
                "score": "positive_sentiment_probability/v1"
            },
            "allowed_side_effects": [],
            "invariants": [
                {
                    "id": "bounded-score",
                    "field": "score",
                    "constraint": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 1
                    }
                }
            ],
            "comparison_fields": [
                "score"
            ],
            "minimum_fixtures": 2
        },
        "incumbent_capability": {
            "id": "provider-a/v1",
            "goal_id": "sentiment-score/v1",
            "input_schema": {
                "type": "object",
                "properties": {
                    "text": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100
                    }
                },
                "required": [
                    "text"
                ],
                "additionalProperties": false
            },
            "output_schema": {
                "type": "object",
                "properties": {
                    "score": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 1
                    }
                },
                "required": [
                    "score"
                ],
                "additionalProperties": false
            },
            "output_semantics": {
                "score": "positive_sentiment_probability/v1"
            },
            "side_effects": []
        },
        "candidate_capability": {
            "id": "provider-b/v1",
            "goal_id": "sentiment-score/v1",
            "input_schema": {
                "type": "object",
                "properties": {
                    "text": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100
                    }
                },
                "required": [
                    "text"
                ],
                "additionalProperties": false
            },
            "output_schema": {
                "type": "object",
                "properties": {
                    "score": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 1
                    }
                },
                "required": [
                    "score"
                ],
                "additionalProperties": false
            },
            "output_semantics": {
                "score": "positive_sentiment_probability/v1"
            },
            "side_effects": []
        },
        "fixtures": [
            {
                "id": "positive",
                "input": {
                    "text": "good"
                },
                "incumbent_output": {
                    "score": 0.9
                },
                "candidate_output": {
                    "score": 0.9
                },
                "incumbent_side_effects": [],
                "candidate_side_effects": []
            },
            {
                "id": "negative",
                "input": {
                    "text": "bad"
                },
                "incumbent_output": {
                    "score": 0.1
                },
                "candidate_output": {
                    "score": 0.1
                },
                "incumbent_side_effects": [],
                "candidate_side_effects": []
            }
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("bono718/agent-capability-substitution-resolver").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "request": {
        "task_contract": {
            "goal_id": "sentiment-score/v1",
            "input_schema": {
                "type": "object",
                "properties": { "text": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100,
                    } },
                "required": ["text"],
                "additionalProperties": False,
            },
            "output_schema": {
                "type": "object",
                "properties": { "score": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 1,
                    } },
                "required": ["score"],
                "additionalProperties": False,
            },
            "output_semantics": { "score": "positive_sentiment_probability/v1" },
            "allowed_side_effects": [],
            "invariants": [{
                    "id": "bounded-score",
                    "field": "score",
                    "constraint": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 1,
                    },
                }],
            "comparison_fields": ["score"],
            "minimum_fixtures": 2,
        },
        "incumbent_capability": {
            "id": "provider-a/v1",
            "goal_id": "sentiment-score/v1",
            "input_schema": {
                "type": "object",
                "properties": { "text": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100,
                    } },
                "required": ["text"],
                "additionalProperties": False,
            },
            "output_schema": {
                "type": "object",
                "properties": { "score": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 1,
                    } },
                "required": ["score"],
                "additionalProperties": False,
            },
            "output_semantics": { "score": "positive_sentiment_probability/v1" },
            "side_effects": [],
        },
        "candidate_capability": {
            "id": "provider-b/v1",
            "goal_id": "sentiment-score/v1",
            "input_schema": {
                "type": "object",
                "properties": { "text": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100,
                    } },
                "required": ["text"],
                "additionalProperties": False,
            },
            "output_schema": {
                "type": "object",
                "properties": { "score": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 1,
                    } },
                "required": ["score"],
                "additionalProperties": False,
            },
            "output_semantics": { "score": "positive_sentiment_probability/v1" },
            "side_effects": [],
        },
        "fixtures": [
            {
                "id": "positive",
                "input": { "text": "good" },
                "incumbent_output": { "score": 0.9 },
                "candidate_output": { "score": 0.9 },
                "incumbent_side_effects": [],
                "candidate_side_effects": [],
            },
            {
                "id": "negative",
                "input": { "text": "bad" },
                "incumbent_output": { "score": 0.1 },
                "candidate_output": { "score": 0.1 },
                "incumbent_side_effects": [],
                "candidate_side_effects": [],
            },
        ],
    } }

# Run the Actor and wait for it to finish
run = client.actor("bono718/agent-capability-substitution-resolver").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "request": {
    "task_contract": {
      "goal_id": "sentiment-score/v1",
      "input_schema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        },
        "required": [
          "text"
        ],
        "additionalProperties": false
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "score": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        },
        "required": [
          "score"
        ],
        "additionalProperties": false
      },
      "output_semantics": {
        "score": "positive_sentiment_probability/v1"
      },
      "allowed_side_effects": [],
      "invariants": [
        {
          "id": "bounded-score",
          "field": "score",
          "constraint": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        }
      ],
      "comparison_fields": [
        "score"
      ],
      "minimum_fixtures": 2
    },
    "incumbent_capability": {
      "id": "provider-a/v1",
      "goal_id": "sentiment-score/v1",
      "input_schema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        },
        "required": [
          "text"
        ],
        "additionalProperties": false
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "score": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        },
        "required": [
          "score"
        ],
        "additionalProperties": false
      },
      "output_semantics": {
        "score": "positive_sentiment_probability/v1"
      },
      "side_effects": []
    },
    "candidate_capability": {
      "id": "provider-b/v1",
      "goal_id": "sentiment-score/v1",
      "input_schema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        },
        "required": [
          "text"
        ],
        "additionalProperties": false
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "score": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        },
        "required": [
          "score"
        ],
        "additionalProperties": false
      },
      "output_semantics": {
        "score": "positive_sentiment_probability/v1"
      },
      "side_effects": []
    },
    "fixtures": [
      {
        "id": "positive",
        "input": {
          "text": "good"
        },
        "incumbent_output": {
          "score": 0.9
        },
        "candidate_output": {
          "score": 0.9
        },
        "incumbent_side_effects": [],
        "candidate_side_effects": []
      },
      {
        "id": "negative",
        "input": {
          "text": "bad"
        },
        "incumbent_output": {
          "score": 0.1
        },
        "candidate_output": {
          "score": 0.1
        },
        "incumbent_side_effects": [],
        "candidate_side_effects": []
      }
    ]
  }
}' |
apify call bono718/agent-capability-substitution-resolver --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bono718/agent-capability-substitution-resolver"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/vJpnaeSv4nRFYrxiU/builds/K1420cbFKn7gaJ8Uo/openapi.json
