# Agent Future Obligation Exposure Resolver (`bono718/agent-future-obligation-exposure-resolver`) Actor

Calculate future obligations, cancellation costs and hold liquidity from structured transaction terms. Exact decimal amounts; explicit unknown liability.

- **URL**: https://apify.com/bono718/agent-future-obligation-exposure-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 $2.00 / 1,000 future exposure 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 Future Obligation Exposure Resolver

Before an agent accepts a subscription, reservation or deferred-payment transaction, calculate the remaining future exposure from structured terms.

Returns `NO_FUTURE_EXPOSURE`, `BOUNDED`, `CONDITIONAL`, `UNBOUNDED_OR_UNKNOWN` or `INSUFFICIENT_TERMS`, plus cash now, hard commitment, conditional maximum, expected scenario, maximum future exposure, reserve and cancellation deadlines. Deterministic JavaScript, exact decimal arithmetic, no LLM or external calls.

### Quick start

On Apify paste `{"request": ...}` using the complete request from [complete JSON demo](https://github.com/bonometti718/C.I-Factory/blob/main/CI-006-demo.md). HTTP channels take that request directly, without the wrapper. Each successful Actor run writes one result to the default dataset and `OUTPUT` to the key-value store.

The example has 10.00 USD cash now, 12 future monthly payments of 20.00, a remaining minimum commitment of 40.00 and a 5.00 cancellation penalty. Maximum future exposure is 240.00, hard committed is 45.00, expected continuing exposure is 240.00 and conservative reserve is 240.00. Immediate cash is separate.

### Input contract

Use one currency per request: `{code:"USD",decimals:2}`. The code is an identifier, not a verified currency registry. All money values are nonnegative decimal strings, at most 15 integral digits, with fractional precision no greater than `decimals` (0..6). Outputs use fixed decimal strings; `null` means unknown. Probabilities are decimal strings from 0 to 1, up to six places.

`transaction` requires `id`, `cash_now` and `terms_complete`. `evaluation_time` requires a timestamp with timezone and seconds (1970..2200). `obligations` is an array, max 1000, unique IDs; request max 64 KiB. Unknown fields are rejected. Set `terms_complete:false` when the supplied list or transaction terms are incomplete: aggregate estimates become unknown.

#### PAYMENT

Required: `id`, `kind:"PAYMENT"`, `amount` (per occurrence, or null for variable/unknown), `frequency` (`ONCE`, `DAY`, `WEEK`, `MONTH`, `YEAR`) and `starts_at` strictly after evaluation time. Supply **remaining future obligations only**: past paid/unpaid installments are not inferred. Current charges belong in cash_now.

Optional fields:

- `interval`: integer 1..120 for recurring schedules.
- `occurrences`: remaining count, 1..1,000,000. ONCE permits only 1 and no interval.
- `ends_at`: inclusive last permitted occurrence. If both count and end are given, the earlier limit wins. Recurrences without either limit are open ended, never truncated to an invented horizon. UTC calendar monthly/yearly schedules clamp to month end using the original anchor day.
- `condition`: `{state:"TRUE"|"FALSE"|"UNKNOWN",probability?:"0.25"}`. Probability is accepted only for UNKNOWN. FALSE eliminates that obligation; UNKNOWN has zero unconditional hard commitment and full conditional maximum. Missing probability makes its expected value unknown.
- `cancellation`: `{allowed_until:timestamp|null}`. Explicit null means cancellable anytime. At the deadline it is still cancellable; after it, the right is expired. Omitted cancellation means no optional exit. This is a snapshot of current exit rights, not a model of changing future penalties.
- `minimum_commitment`: total remaining minimum floor for this obligation, default zero. It is a floor, not an extra installment added to the schedule.
- `termination_penalty`: additional cost on top of the minimum floor to cancel now, default zero when omitted; explicit null means unknown. Requires cancellation terms.
- `maximum_amount`: an explicit **all-in total cap** across this entire obligation, including penalties. It is not a per-period cap. It overrides a higher uncapped scheduled total. A cap below the minimum floor plus known cancellation penalty is invalid.
- `expected_amount`: caller estimate of the entire continuing scenario, before condition probability; must be between the minimum floor and continuing exposure. Omit for known fixed schedules. For variable amounts without a caller estimate, expected exposure remains unknown even with a known cap.

Normalize tiered costs or changing terms into separate obligations. Every charge must be represented once. No free-text clauses, usage-price inference, graduated cancellation schedule or cross-obligation conditional dependency resolution is supported in v0.1.0.

#### AUTHORIZATION_HOLD

Required: `id`, `kind:"AUTHORIZATION_HOLD"`, `amount` (or null), `starts_at` and `release_at` (timestamp or null). Normalize an already active hold to evaluation_time; future starts must be at or after it. Release cannot precede start. Optional `covers_obligation_id` explicitly identifies the PAYMENT whose eventual charge the hold covers.

A hold is liquidity, not an expense. It does not enter maximum exposure or hard commitment. Unknown amount yields insufficient terms; unknown release produces a warning. Linking is a caller assertion: use it only when the hold really covers that charge.

### Calculation policy

- `cash_now` is immediate cash, excluded from all future totals.
- `hard_committed` is the minimum unavoidable future amount under the currently declared exit rights. Known fixed payment: continuing total, or the smaller of continuing total and minimum floor plus exit penalty if cancellable. Unknown variable payment without an exit: the declared minimum floor. Unknown fixed infinite commitment or exit fee can make this value null.
- `maximum_exposure` sums each possible future liability, including optional cancellation branches. A fixed finite schedule is bounded; open nonzero recurrence, variable amount without a total cap or unknown possible exit fee can make it null. No finite horizon is substituted.
- `expected_exposure` models continuing **without optional cancellation**, using caller estimates and condition probabilities, with half-up rounding per obligation to minor units. It is a scenario, not a statistical forecast or optimal policy. Correlations are not modeled.
- `conditional_exposure.maximum` is the sum of maximum liability of UNKNOWN-condition payments, before probability weighting.
- `recommended_reserve` is a conservative liquidity envelope, not financial advice: for each payment take the larger of its maximum and the sum of explicitly linked holds; add all unlinked holds. It ignores timing offsets and possible reuse of liquidity. Unknown maximum or hold amount makes reserve unknown. Excludes cash_now.
- `cancellable_until` is the earliest finite active cancellation deadline. Null can mean no finite deadline or no cancellable obligation; inspect per-obligation details. `next_irreversible_at` is the earliest finite deadline or evaluation_time for a currently noncancellable possible obligation.

Decision precedence: missing required terms → INSUFFICIENT_TERMS; unknown maximum/reserve → UNBOUNDED_OR_UNKNOWN; positive conditional liability → CONDITIONAL; zero future exposure and zero hold reserve → NO_FUTURE_EXPOSURE; otherwise BOUNDED. BOUNDED says nothing about affordability or suitability.

### Limits and trust

The caller supplies terms, completeness, caps, conditions and probabilities. They are not independently authenticated. This API does not read contracts, verify law, assess credit, recommend financial products, perform FX, infer taxes, discount cash flows, debit wallets or execute payments. A hold's eventual conversion into a charge must be separately represented as a PAYMENT. Do not treat a sample or passing tests as certification of a real contract.

Input schema: [schema-input.json](https://github.com/bonometti718/C.I-Factory/blob/main/schemas/CI-006-input.json). Full calculation policy and worked examples: https://github.com/bonometti718/C.I-Factory/blob/main/capabilities/CI-006.md.

Contact: bonometti.work.ai@gmail.com

# Actor input Schema

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

Amounts are decimal strings. Normalize future remaining obligations; read README for all-in caps, cancellation and reserve policy.

## Actor input object example

```json
{
  "request": {
    "transaction": {
      "id": "subscription-review",
      "cash_now": "10.00",
      "terms_complete": true
    },
    "currency": {
      "code": "USD",
      "decimals": 2
    },
    "evaluation_time": "2026-10-18T12:00:00Z",
    "obligations": [
      {
        "id": "monthly-plan",
        "kind": "PAYMENT",
        "amount": "20.00",
        "frequency": "MONTH",
        "starts_at": "2026-11-01T00:00:00Z",
        "occurrences": 12,
        "minimum_commitment": "40.00",
        "cancellation": {
          "allowed_until": null
        },
        "termination_penalty": "5.00"
      }
    ]
  }
}
```

# 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": {
        "transaction": {
            "id": "subscription-review",
            "cash_now": "10.00",
            "terms_complete": true
        },
        "currency": {
            "code": "USD",
            "decimals": 2
        },
        "evaluation_time": "2026-10-18T12:00:00Z",
        "obligations": [
            {
                "id": "monthly-plan",
                "kind": "PAYMENT",
                "amount": "20.00",
                "frequency": "MONTH",
                "starts_at": "2026-11-01T00:00:00Z",
                "occurrences": 12,
                "minimum_commitment": "40.00",
                "cancellation": {
                    "allowed_until": null
                },
                "termination_penalty": "5.00"
            }
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("bono718/agent-future-obligation-exposure-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": {
        "transaction": {
            "id": "subscription-review",
            "cash_now": "10.00",
            "terms_complete": True,
        },
        "currency": {
            "code": "USD",
            "decimals": 2,
        },
        "evaluation_time": "2026-10-18T12:00:00Z",
        "obligations": [{
                "id": "monthly-plan",
                "kind": "PAYMENT",
                "amount": "20.00",
                "frequency": "MONTH",
                "starts_at": "2026-11-01T00:00:00Z",
                "occurrences": 12,
                "minimum_commitment": "40.00",
                "cancellation": { "allowed_until": None },
                "termination_penalty": "5.00",
            }],
    } }

# Run the Actor and wait for it to finish
run = client.actor("bono718/agent-future-obligation-exposure-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": {
    "transaction": {
      "id": "subscription-review",
      "cash_now": "10.00",
      "terms_complete": true
    },
    "currency": {
      "code": "USD",
      "decimals": 2
    },
    "evaluation_time": "2026-10-18T12:00:00Z",
    "obligations": [
      {
        "id": "monthly-plan",
        "kind": "PAYMENT",
        "amount": "20.00",
        "frequency": "MONTH",
        "starts_at": "2026-11-01T00:00:00Z",
        "occurrences": 12,
        "minimum_commitment": "40.00",
        "cancellation": {
          "allowed_until": null
        },
        "termination_penalty": "5.00"
      }
    ]
  }
}' |
apify call bono718/agent-future-obligation-exposure-resolver --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bono718/agent-future-obligation-exposure-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/XNCBA50GgpcX0qTA4/builds/oODpfg7QgIUjsWcea/openapi.json
