# Knowledge Base Update & Evidence Feed (`jj_toolworks/jj-knowledge-update-evidence-feed`) Actor

Turn completed document exports into reviewable knowledge-base update plans. Get changed-text actions, metadata patches, coverage holds and a compact evidence package. $0.25 per completed plan, including no-change checks. No crawling or destination writes.

- **URL**: https://apify.com/jj_toolworks/jj-knowledge-update-evidence-feed.md
- **Developed by:** [JJ Toolworks](https://apify.com/jj_toolworks) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.25 / completed knowledge-update plan

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

## Knowledge Base Update and Evidence Feed

Turn completed document exports into a reviewable knowledge-base update plan. Identify new text, metadata changes, unchanged content and documents that need to be held for review. Useful for agencies and developers maintaining client documentation or AI retrieval systems.

**Price: $0.25 per completed bounded plan**, including a no-change check. The fee is requested only after the output artifacts and completion manifest are saved. Rejected inputs and failures before complete delivery request no JJ processing fee. No startup or dataset-item fee is configured. A completed plan can include held documents. This Actor prepares work; it does not apply it to a customer system.

### Start with the example

1. Keep Input mode set to `inline` and Output delivery set to `compact`.
2. The Planning contract example contains two explicitly synthetic documents. Replace them with documents you are authorized to process. Use stable IDs, URLs, titles, text, extractionProfile and fetchedAt timestamps.
3. Keep namespace, scope and extraction settings stable between cycles. Include an acknowledged applied baseline when comparing an update. A first run without a baseline proposes an initial import.
4. Use 512 MB, restart on error Off, and a maximum run cost of at least $0.25. A $0.50 cap is suitable for the example. For owner development runs, Apify can display platform usage separately.
5. Inspect the summary and evidence review. Download the records named by the complete manifest before consuming the plan.

The example inventory is partial. Do not mark a delta, a truncated export or a failed crawl as a complete inventory. Omitted or failed documents retain their previous evidence rather than silently becoming deletions. Proposed text removals still require review.

### Input contracts

This release accepts supplied exports only. `plannerInput.source.format` supports `documents`, JJ Bulk Website Content Export rows (`jj-content`), and JJ Website Change Monitor rows (`jj-changes`). Arbitrary third-party crawler output needs explicit field mapping; it is not a verified native integration. Live producer-dataset ingestion is outside the verified release.

For `documents`, each healthy item needs a stable `id`, `url`, original `text`, `complete: true`, `extractionProfile` and a valid `fetchedAt`. Source completion and immutability are caller assertions. Preserve error rows and scope/coverage information so the plan can distinguish uncertainty from confirmed changes. Use the supplied two-document example to learn the envelope before loading a larger export.

### What you receive

- One summary row with counts of new, changed, unchanged and held documents and proposed actions.
- A document-level HTML review and CSV work list.
- A lossless plan package with actions, citations, passages, holds and a candidate baseline.
- Source-verification notes, a completion manifest, and a separate billing receipt.

Compact delivery stores evidence once in bounded compressed parts. `PLAN` is the package index; `ACTIONS` and `CANDIDATE_SNAPSHOT` are references into that plan. They are not standalone action arrays or an already-applied baseline. Legacy mode returns full JSON artifacts and reaches size limits sooner.

### Consumer handoff and recurring checks

The companion Node.js 22+ source package includes a free local compatibility checker, decoder and receipt helper; it uses no third-party libraries. The checker evaluates the actual input and output size before a cloud run:

```sh
node src/check-cli.mjs examples/quick-start.json
```

To decode compact output, save all JSON records as `KEY.json`, the CSV as `REVIEW.csv`, the report as `REVIEW_HTML.html`, and each binary part as `PLAN_PART_001.bin` etc. Keep `MANIFEST.json` with them:

```sh
node src/decode-cli.mjs downloaded-records decoded-plan.json
```

The decoder checks every record size/hash, part order, decompression bound and reconstructed plan identity. Checksums detect corruption; they do not authenticate a sender.

After reviewing the holds and completing the destination work, generate a receipt template:

```sh
node src/ack-cli.mjs --receipt-template decoded-plan.json receipt.json
```

The template starts with `confirmedApplied: false`. Confirm actual destination success for every listed action, enter the actual reviewer/time, and only then set it to true. Create the next baseline with:

```sh
node src/ack-cli.mjs decoded-plan.json receipt.json applied-baseline.json
```

The helper rejects partial or mismatched receipts and never overwrites existing evidence. It checks a caller's acknowledgement; it neither connects to a destination nor independently verifies that the work happened. Supply the resulting baseline in the next Planning contract to avoid re-proposing already applied work.

### Limits and failure behavior

Cloud input is limited to 8 MiB including baseline. Safety ceilings are 1,000 documents, 25,000 chunks, 8 MiB source text and a 24 MiB serialized plan. These are maximum guards, not a promised usable batch size: text density and baseline size matter. Binary parts are at most 1 MiB and compressed plan data at most 8 MiB. The free checker reports actual compatibility and delivery sizes. Split oversized work into explicit stable scopes; do not silently truncate it.

No crawling, embeddings, automated deletion, alerts, subscriptions or destination synchronization is included. Failed or uncertain sources remain visible as holds. The run uses limited permissions and its own storage. Do not put passwords or API keys in input.

Fee requests are never automatically retried. A durable journal blocks rebilling on restart or resurrection. A billing response can be uncertain, and an acknowledged event can appear in run metadata after the immediate receipt readback. A failure writing a billing receipt after the fee was accepted does not undo the committed output or fee. Inspect the manifest and run event counts before restarting; there is no automatic refund or recharge workflow.

### Validation

The local regression suite passes 141 tests. Completed-plan, no-change and rejected-input private cloud tests recorded exactly 1, 1 and 0 plan-fee events. Both completed plans passed all eight output checksums and exactly matched their local plans. Earlier compact delivery also passed a 100-document synthetic cloud test. These are technical and owner-operated tests, not proof of customer savings, collected payment, destination acceptance or repeat paid demand.

# Actor input Schema

## `deliveryMode` (type: `string`):

Legacy returns full JSON artifacts. Compact stores one lossless gzip plan in bounded parts with a working report and offline decoder; ACTIONS and CANDIDATE_SNAPSHOT become references, not full objects. Core safety limits remain unchanged.

## `mode` (type: `string`):

Supply an export in plannerInput.source. This release does not read a live producer dataset.

## `plannerInput` (type: `object`):

namespace, checkedAt, explicit scope, source and optional acknowledged baseline. Begin with the example below. Replace example documents with your export. Keep identity, scope and extractionProfile stable across cycles.

## Actor input object example

```json
{
  "deliveryMode": "compact",
  "mode": "inline",
  "plannerInput": {
    "synthetic": true,
    "namespace": "example-support-docs",
    "checkedAt": "2026-10-13T12:00:00Z",
    "scope": {
      "id": "example-support-section",
      "definition": "Exactly the two example documents below; no whole-site inventory claim."
    },
    "chunkBytes": 1200,
    "source": {
      "format": "documents",
      "completed": true,
      "immutable": true,
      "inventoryComplete": false,
      "reference": "SYNTHETIC example; replace with your dated export",
      "items": [
        {
          "id": "returns",
          "url": "https://example.test/help/returns",
          "title": "Example returns policy",
          "text": "SYNTHETIC: This example policy describes where customers can review return instructions. Replace this text with your actual export.",
          "complete": true,
          "extractionProfile": "example-v1",
          "fetchedAt": "2026-10-13T12:00:00Z"
        },
        {
          "id": "shipping",
          "url": "https://example.test/help/shipping",
          "title": "Example shipping policy",
          "text": "SYNTHETIC: This example document describes shipping information. Replace this text with your actual export.",
          "complete": true,
          "extractionProfile": "example-v1",
          "fetchedAt": "2026-10-13T12:00:00Z"
        }
      ]
    }
  }
}
```

# Actor output Schema

## `summary` (type: `string`):

No description

## `review` (type: `string`):

No description

## `plan` (type: `string`):

No description

## `manifest` (type: `string`):

No description

## `sourceEvidence` (type: `string`):

No description

## `billing` (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 = {
    "deliveryMode": "compact",
    "mode": "inline",
    "plannerInput": {
        "synthetic": true,
        "namespace": "example-support-docs",
        "checkedAt": "2026-10-13T12:00:00Z",
        "scope": {
            "id": "example-support-section",
            "definition": "Exactly the two example documents below; no whole-site inventory claim."
        },
        "chunkBytes": 1200,
        "source": {
            "format": "documents",
            "completed": true,
            "immutable": true,
            "inventoryComplete": false,
            "reference": "SYNTHETIC example; replace with your dated export",
            "items": [
                {
                    "id": "returns",
                    "url": "https://example.test/help/returns",
                    "title": "Example returns policy",
                    "text": "SYNTHETIC: This example policy describes where customers can review return instructions. Replace this text with your actual export.",
                    "complete": true,
                    "extractionProfile": "example-v1",
                    "fetchedAt": "2026-10-13T12:00:00Z"
                },
                {
                    "id": "shipping",
                    "url": "https://example.test/help/shipping",
                    "title": "Example shipping policy",
                    "text": "SYNTHETIC: This example document describes shipping information. Replace this text with your actual export.",
                    "complete": true,
                    "extractionProfile": "example-v1",
                    "fetchedAt": "2026-10-13T12:00:00Z"
                }
            ]
        }
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("jj_toolworks/jj-knowledge-update-evidence-feed").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 = {
    "deliveryMode": "compact",
    "mode": "inline",
    "plannerInput": {
        "synthetic": True,
        "namespace": "example-support-docs",
        "checkedAt": "2026-10-13T12:00:00Z",
        "scope": {
            "id": "example-support-section",
            "definition": "Exactly the two example documents below; no whole-site inventory claim.",
        },
        "chunkBytes": 1200,
        "source": {
            "format": "documents",
            "completed": True,
            "immutable": True,
            "inventoryComplete": False,
            "reference": "SYNTHETIC example; replace with your dated export",
            "items": [
                {
                    "id": "returns",
                    "url": "https://example.test/help/returns",
                    "title": "Example returns policy",
                    "text": "SYNTHETIC: This example policy describes where customers can review return instructions. Replace this text with your actual export.",
                    "complete": True,
                    "extractionProfile": "example-v1",
                    "fetchedAt": "2026-10-13T12:00:00Z",
                },
                {
                    "id": "shipping",
                    "url": "https://example.test/help/shipping",
                    "title": "Example shipping policy",
                    "text": "SYNTHETIC: This example document describes shipping information. Replace this text with your actual export.",
                    "complete": True,
                    "extractionProfile": "example-v1",
                    "fetchedAt": "2026-10-13T12:00:00Z",
                },
            ],
        },
    },
}

# Run the Actor and wait for it to finish
run = client.actor("jj_toolworks/jj-knowledge-update-evidence-feed").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 '{
  "deliveryMode": "compact",
  "mode": "inline",
  "plannerInput": {
    "synthetic": true,
    "namespace": "example-support-docs",
    "checkedAt": "2026-10-13T12:00:00Z",
    "scope": {
      "id": "example-support-section",
      "definition": "Exactly the two example documents below; no whole-site inventory claim."
    },
    "chunkBytes": 1200,
    "source": {
      "format": "documents",
      "completed": true,
      "immutable": true,
      "inventoryComplete": false,
      "reference": "SYNTHETIC example; replace with your dated export",
      "items": [
        {
          "id": "returns",
          "url": "https://example.test/help/returns",
          "title": "Example returns policy",
          "text": "SYNTHETIC: This example policy describes where customers can review return instructions. Replace this text with your actual export.",
          "complete": true,
          "extractionProfile": "example-v1",
          "fetchedAt": "2026-10-13T12:00:00Z"
        },
        {
          "id": "shipping",
          "url": "https://example.test/help/shipping",
          "title": "Example shipping policy",
          "text": "SYNTHETIC: This example document describes shipping information. Replace this text with your actual export.",
          "complete": true,
          "extractionProfile": "example-v1",
          "fetchedAt": "2026-10-13T12:00:00Z"
        }
      ]
    }
  }
}' |
apify call jj_toolworks/jj-knowledge-update-evidence-feed --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jj_toolworks/jj-knowledge-update-evidence-feed"
        }
    }
}
```

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/ihK5nrgvPrpR47uVd/builds/ytSuw8KmxDwuqlpFN/openapi.json
