{"_id":"@ar.io/anchor-langchain","_rev":"2-868301109d46213a2683e142dc0cb591","name":"@ar.io/anchor-langchain","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@ar.io/anchor-langchain","version":"0.1.0","keywords":["ar.io","arweave","langchain","ai","agents","provenance","audit-trail","anchoring"],"license":"MIT","_id":"@ar.io/anchor-langchain@0.1.0","maintainers":[{"name":"vilenarios","email":"info@ardrive.io"}],"homepage":"https://github.com/ar-io/ar-io-anchor/tree/main/packages/langchain","bugs":{"url":"https://github.com/ar-io/ar-io-anchor/issues"},"dist":{"shasum":"dcb70f7917ecb7146af3fe34ee356ecf0885665e","tarball":"https://registry.npmjs.org/@ar.io/anchor-langchain/-/anchor-langchain-0.1.0.tgz","fileCount":8,"integrity":"sha512-wWaYt4NU9koz81Ve2iE/AyAlAqObrFn2MOzZ831Fm+C64N4+4XwHZyD7Zk3BZY58GVK+FJOzog8wFiXD5siNxQ==","signatures":[{"sig":"MEUCIG1bSpcPVzD6JJkThuAeV7G1HQTGSN2ovXeIpOKQ2SHbAiEA8XkDzc9swFBJhULpQotK1O92MXRc5a4BfnkKTgB2EeY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":37812},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"7a4f5477de2e538afc177d61a897f782dd2ff043","scripts":{"build":"tsc -p tsconfig.build.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"vilenarios","email":"info@ardrive.io"},"repository":{"url":"git+https://github.com/ar-io/ar-io-anchor.git","type":"git","directory":"packages/langchain"},"_npmVersion":"10.8.2","description":"Anchor your LangChain.js agent's run tree as it executes: one callback handler turns every chain/LLM/tool step into a Merkle-batched, individually inclusion-proofed provenance record on ar.io — prompts and outputs are hashed locally and never uploaded.","directories":{},"sideEffects":false,"_nodeVersion":"20.18.2","dependencies":{"@ar.io/anchor":"^0.1.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"@ar.io/proof":"^0.2.0","@langchain/core":"^1.0.0"},"peerDependencies":{"@langchain/core":"^1.0.0"},"_npmOperationalInternal":{"tmp":"tmp/anchor-langchain_0.1.0_1781623230544_0.8311323969890516","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@ar.io/anchor-langchain","version":"0.2.0","description":"Anchor your LangChain.js agent's run tree as it executes: one callback handler turns every chain/LLM/tool step into a Merkle-batched, individually inclusion-proofed provenance record on ar.io — prompts and outputs are hashed locally and never uploaded.","license":"MIT","type":"module","sideEffects":false,"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsc -p tsconfig.build.json","prepublishOnly":"npm run build"},"dependencies":{"@ar.io/anchor":"^0.2.0"},"peerDependencies":{"@langchain/core":"^1.0.0"},"devDependencies":{"@langchain/core":"^1.0.0","@ar.io/proof":"^0.2.0"},"repository":{"type":"git","url":"git+https://github.com/ar-io/ar-io-anchor.git","directory":"packages/langchain"},"homepage":"https://github.com/ar-io/ar-io-anchor/tree/main/packages/langchain","publishConfig":{"access":"public"},"keywords":["ar.io","arweave","langchain","ai","agents","provenance","audit-trail","anchoring"],"gitHead":"f47f769b080b7d87a59f2ab9b6dcbb9eb25661f6","_id":"@ar.io/anchor-langchain@0.2.0","bugs":{"url":"https://github.com/ar-io/ar-io-anchor/issues"},"_nodeVersion":"22.23.0","_npmVersion":"11.18.0","dist":{"integrity":"sha512-jroZ/ihPk+r+uHWpLczYTndfTofhsUtwgrnc97Ln0fSVRef1PL9d0RYSMt8mym7SZm1ABJMCLg7VBVKbInnRfg==","shasum":"118098bf0204279da2cc618a7a70f4dd0b24367b","tarball":"https://registry.npmjs.org/@ar.io/anchor-langchain/-/anchor-langchain-0.2.0.tgz","fileCount":8,"unpackedSize":39615,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ar.io%2fanchor-langchain@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIBwO/yAK93KADXfGEtVrhOVPO+Dtf/Y4GxiJrgxI3ZsZAiEA83+J8hx9GF9yGQTxHPsoX7esiikGfkLBIEkw3LPPlPo="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:17d5d56f-6afc-456c-af3a-a0420bb3270c"}},"directories":{},"maintainers":[{"name":"vilenarios","email":"info@ardrive.io"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/anchor-langchain_0.2.0_1782831958083_0.5598156320814149"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-16T15:20:30.397Z","modified":"2026-06-30T15:05:59.347Z","0.1.0":"2026-06-16T15:20:30.679Z","0.2.0":"2026-06-30T15:05:58.237Z"},"bugs":{"url":"https://github.com/ar-io/ar-io-anchor/issues"},"license":"MIT","homepage":"https://github.com/ar-io/ar-io-anchor/tree/main/packages/langchain","keywords":["ar.io","arweave","langchain","ai","agents","provenance","audit-trail","anchoring"],"repository":{"type":"git","url":"git+https://github.com/ar-io/ar-io-anchor.git","directory":"packages/langchain"},"description":"Anchor your LangChain.js agent's run tree as it executes: one callback handler turns every chain/LLM/tool step into a Merkle-batched, individually inclusion-proofed provenance record on ar.io — prompts and outputs are hashed locally and never uploaded.","maintainers":[{"name":"vilenarios","email":"info@ardrive.io"}],"readme":"# @ar.io/anchor-langchain\n\nAnchor your agent's run tree as it executes. Add one callback handler, and every chain, chat-model, LLM, tool, and retriever step becomes a tamper-evident provenance record:\n\n1. events are **Merkle-batched on the hot path** — a whole agent session is ONE write to Arweave (via [Turbo](https://ardrive.io/turbo), ar.io's upload service), not one per step,\n2. every event still gets its **own standalone inclusion proof**, verifiable offline against the batch checkpoint,\n3. prompts, outputs, and tool I/O are **hashed locally and never uploaded** — the on-chain envelope carries only the hash (`ario.events/v1`, Minimal disclosure).\n\n```bash\nnpm install @ar.io/anchor-langchain @ar.io/anchor @langchain/core\n```\n\n```ts\nimport { createAnchorer } from \"@ar.io/anchor\";\nimport { anchorCallbacks } from \"@ar.io/anchor-langchain\";\n\nconst provenance = anchorCallbacks(createAnchorer()); // dev mode: zero config\n\n// One line of integration: pass it like any LangChain callback.\nconst answer = await agent.invoke(\n  { input: \"Summarize the Q2 incident reports\" },\n  { callbacks: [provenance] },\n);\n\n// End of run / request / process: flush and collect the proofs.\nconst receipts = await provenance.close();\nfor (const r of receipts) {\n  console.log(r.envelope.event_id, \"→ checkpoint\", r.checkpointTxId, `leaf ${r.leafIndex}/${r.leafCount}`);\n  // r.recordBytes is YOUR copy of what the hash commits to — retain it.\n}\n```\n\nProduction refuses auto-generated secrets — `createAnchorer({ environment: \"production\", signer, wallet })` per [`@ar.io/anchor`](https://github.com/ar-io/ar-io-anchor/tree/main/packages/anchor)'s structural gate. Dev proofs are permanently marked `environment: \"dev\"` inside the signed bytes.\n\n## The run tree is the record\n\nLangChain's callbacks carry `runId`/`parentRunId` for every step. The handler commits that linkage — plus its own per-run event chain — inside every hash-committed record's metadata:\n\n```json\n\"langchain\": {\n  \"run_id\": \"…\",          // this step\n  \"parent_run_id\": \"…\",   // its parent in the run tree\n  \"root_run_id\": \"…\",     // the top-level invocation it belongs to\n  \"seq\": 3,               // its ordinal within that root run\n  \"prev_event_id\": \"…\"    // the previous event's envelope event_id\n}\n```\n\nEach record points at its predecessor, and every pointer lives inside individually signed, inclusion-proofed bytes. Drop an event and the next one's pointer dangles; reorder them and `seq` disagrees; edit one and its hash breaks. The result: a **deletion-evident, reorder-evident tree of everything the agent did**, reconstructable offline from the receipts alone.\n\n## Event vocabulary\n\n`langchain.chain_start/_end/_error`, `langchain.chat_model_start`, `langchain.llm_start/_end/_error`, `langchain.tool_start/_end/_error`, `langchain.retriever_start/_end` — one event type per anchored callback (exported as `EVENT_TYPES`).\n\n## Controlling what the hash commits to\n\nNothing leaves your process either way — but the committed record is what you must retain and what an auditor will ask for. `mapPayload` runs before the hash is computed:\n\n```ts\nconst provenance = anchorCallbacks(anchorer, {\n  batch: { maxEvents: 64, flushOnIdle: 2_000 },          // batching knobs (first trigger wins)\n  mapPayload: (e) => {\n    if (e.type === \"langchain.retriever_end\") return null; // skip entirely\n    return { ...e.payload, prompts: undefined };           // or redact fields\n  },\n});\n```\n\nSkipped events consume no sequence number — the committed chain stays gapless.\n\n## Verifying\n\nCollect the receipts, serialize them into ONE signed, portable `trace-bundle.json`, and hand it to an auditor — they verify the whole thing (every event's signature + payload binding + Merkle inclusion, offline) with **one command** and the read-only [`@ar.io/proof`](https://www.npmjs.com/package/@ar.io/proof) (no write SDK in the trust path):\n\n```ts\nconst receipts = await provenance.close();\nconst bundle = await ario.bundle(receipts); // signed with the anchorer's own key — zero ceremony\nawait fs.writeFile(\"trace-bundle.json\", JSON.stringify(bundle, null, 2));\n```\n\n> Want the auditor to read the actual run — the raw step bytes, not just verify their hashes? Pass `ario.bundle(receipts, { disclose })` (keyed by `eventId`) to embed selected events' bytes inside the signed bundle — opt-in, default off, on-chain footprint unchanged. See [disclosure in the core README](https://github.com/ar-io/ar-io-anchor/blob/main/packages/anchor/README.md#optionally-include-the-raw-logs-opt-in-default-off).\n\n```bash\nnpx @ar.io/proof verify trace-bundle.json\n# optionally re-fetch each checkpoint on-chain to confirm it's anchored:\nnpx @ar.io/proof verify trace-bundle.json https://arweave.net,https://permagate.io\n```\n\nThe whole story is five steps: anchor → `await provenance.close()` → `await ario.bundle(receipts)` → write `trace-bundle.json` → `npx @ar.io/proof verify trace-bundle.json`. Need an explicit key or to override the issuer/gateway? The advanced form is `toEvidenceBundle(receipts, { signer, issuer })` from `@ar.io/anchor`.\n\nIt prints a per-event + rollup verdict and exits on a pinned code (`0` verified · `1` failed · `2` malformed · `3` gateway-unavailable); the producer's asserted verdict is shown but never trusted (the verdict is recomputed from the body). A **withheld** record surfaces as semantics-undetermined (`~`), not a failure.\n\n> **Live:** the bundle emit (`ario.bundle()` / `toEvidenceBundle`) ships in `@ar.io/anchor` ≥ 0.1.3 and the `npx @ar.io/proof verify` CLI in `@ar.io/proof` ≥ 0.2.2. The `@ar.io/proof` primitives below remain available for manual/advanced verification.\n\nA single receipt also verifies by hand against the read-only kernel (`@ar.io/proof` `^0.2.0`, the full-family verifier):\n\n```ts\nimport { verifyEnvelope, verifyInclusion, hexToBytes } from \"@ar.io/proof\";\n\n// Supply the retained record bytes and the envelope verifies green end-to-end.\nconst result = await verifyEnvelope(r.envelope, { payloadBytes: r.recordBytes });\nresult.ok;            // true — signature + payload binding\nconst inclusionOk = await verifyInclusion(\n  hexToBytes(r.leafHash), r.leafIndex, r.leafCount,\n  r.auditPath.map(hexToBytes), hexToBytes(r.root),\n);\n```\n\n**Without the record** (external commitment), `verifyEnvelope(r.envelope)` confirms the signature but reports **`payloadHashOk: null`** — *semantics-undetermined*, **not** a failure. Treat `null` as \"supply the record to complete the proof,\" never as a pass and never as a tamper; a genuinely tampered record returns `payloadHashOk: false` with `ok: false`. The checkpoint is fetched through any [ar.io gateway](https://gateways.ar.io) (`r.gatewayUrl`) and re-verified the same way — the gateway is delivery, never trust.\n\n## Semantics\n\n- **Hot path is synchronous.** Each callback is one in-memory `batch.add()`; signing and the single upload happen at window flush. An agent step never waits on the network.\n- **Lifecycle is explicit.** `await provenance.close()` flushes and resolves all receipts; there are no hidden process-exit hooks. Long-lived handlers can `flush()` between requests.\n- **Provenance never crashes the agent.** A payload that fails to serialize is reported via `warn` and skipped — the run continues.\n- **Retention is yours.** External commitment means the receipt's `recordBytes` are the only copy of what the hash commits to. Store them (DB row, object store, log archive) — an envelope without its record proves a commitment existed, not what it said.\n- Provenance, not endorsement: a verified history says *what happened* — never \"safe\" or \"approved\".\n\n## License\n\nMIT. The framework is a peer dependency; this package depends only on [`@ar.io/anchor`](https://github.com/ar-io/ar-io-anchor/tree/main/packages/anchor).\n","readmeFilename":"README.md"}