Skip to content

Add MarkovianStampTool for verifiable provenance receipts#6388

Open
MarkovianProtocol wants to merge 2 commits into
crewAIInc:mainfrom
MarkovianProtocol:add-markovian-stamp-tool
Open

Add MarkovianStampTool for verifiable provenance receipts#6388
MarkovianProtocol wants to merge 2 commits into
crewAIInc:mainfrom
MarkovianProtocol:add-markovian-stamp-tool

Conversation

@MarkovianProtocol

@MarkovianProtocol MarkovianProtocol commented Jun 29, 2026

Copy link
Copy Markdown

MarkovianStampTool

Adds a tool that lets a CrewAI agent stamp any output and get back a verifiable provenance receipt in one line. Lives under lib/crewai-tools.

Markovian is a content-agnostic provenance primitive. Stamping commits a hash of the data to the chain, anchored to Bitcoin, and returns a Merkle root plus a public verify URL. It proves data existed at a point in time, not that the data is correct. Provenance, not truth.

Why this is useful for agents

Agents produce decisions, analyses, and artifacts that downstream systems and people need to trust. A stamp gives each output a timestamped, tamper-evident record that anyone can check at https://api.quantsynth.net/verify/<merkle_root>, with no account.

Usage

from crewai_tools import MarkovianStampTool

tool = MarkovianStampTool()
print(tool.run(data="The thesis approved by the agent at 15:00 UTC."))

Output:

Markovian provenance receipt (markovian-provenance/v1):
  merkle_root: 12bebfcc4ae5e951c4f903da6cfd934ccf50be90827ecad63dff9990b2e46168
  block_height: 135223
  verify_url: https://api.quantsynth.net/verify/12bebfcc4ae5e951c4f903da6cfd934ccf50be90827ecad63dff9990b2e46168

Notes

  • No account, wallet, or API key required for the free tier. An optional MARKOVIAN_API_KEY and wallet are supported for attributed usage.
  • Prefers the markovian PyPI SDK and falls back to a plain HTTP POST when the SDK is not installed, so it works with the base requests dependency.
  • Errors are handled and returned as readable strings, no stack traces.

Checklist

  • Tool under lib/crewai-tools/src/crewai_tools/tools/markovian_stamp_tool/
  • Class ends with Tool, subclasses BaseTool
  • Pydantic args_schema with field descriptions
  • Optional env_vars via Field(default_factory=...), lazy SDK import
  • Registered in tools/__init__.py and crewai_tools/__init__.py (imports and __all__)
  • Unit tests in tests/tools/, deterministic, no live network
  • Tool README.md with usage
  • ruff check, ruff format, and pytest green locally

Project: https://markovianprotocol.com
Source (Apache-2.0): https://github.com/MarkovianProtocol/markovian-protocol
SDK: pip install markovian

Summary by CodeRabbit

  • New Features
    • Added a new text provenance stamping tool to the public API (available from both the main package and the tools package).
    • Generates a formatted provenance receipt with a verification link.
  • Documentation
    • Added a full README with installation, configuration options, and example usage (including agent integration).
  • Tests
    • Added tests covering successful stamping (SDK path), HTTP fallback, and user-facing error messages for API failures and unexpected responses.

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 52ef44ad-5f1d-4e0b-a228-7986af12ab6a

📥 Commits

Reviewing files that changed from the base of the PR and between f91cfbb and 95c90ac.

📒 Files selected for processing (3)
  • lib/crewai-tools/src/crewai_tools/tools/markovian_stamp_tool/README.md
  • lib/crewai-tools/src/crewai_tools/tools/markovian_stamp_tool/markovian_stamp_tool.py
  • lib/crewai-tools/tests/tools/markovian_stamp_tool_test.py
✅ Files skipped from review due to trivial changes (1)
  • lib/crewai-tools/src/crewai_tools/tools/markovian_stamp_tool/README.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/crewai-tools/tests/tools/markovian_stamp_tool_test.py
  • lib/crewai-tools/src/crewai_tools/tools/markovian_stamp_tool/markovian_stamp_tool.py

📝 Walkthrough

Walkthrough

Adds a new MarkovianStampTool to the crewai-tools package. The tool stamps text via the Markovian Protocol using an SDK when available, falling back to direct HTTP POST. It returns a provenance receipt with merkle_root, block_height, and verify_url. Package exports, a README, and tests are included.

Changes

MarkovianStampTool

Layer / File(s) Summary
Tool schema, stamping logic, and error handling
lib/crewai-tools/src/crewai_tools/tools/markovian_stamp_tool/markovian_stamp_tool.py
Defines MarkovianStampToolInput (required data, optional label), MarkovianStampTool with api_key/wallet/base_url/timeout init, _stamp with SDK/HTTP fallback, _run with timeout/HTTP/generic error handling and receipt formatting, and _arun async wrapper.
Package exports and README
lib/crewai-tools/src/crewai_tools/__init__.py, lib/crewai-tools/src/crewai_tools/tools/__init__.py, lib/crewai-tools/src/crewai_tools/tools/markovian_stamp_tool/README.md
Imports MarkovianStampTool and adds it to __all__ in both package init files; adds a README covering usage, options, sample output, and agent integration.
Tests
lib/crewai-tools/tests/tools/markovian_stamp_tool_test.py
Tests SDK path, HTTP fallback (forced import failure + requests.post mock), HTTPError handling, non-dictionary responses, and missing merkle_root handling.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding MarkovianStampTool for verifiable provenance receipts.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
lib/crewai-tools/src/crewai_tools/tools/markovian_stamp_tool/markovian_stamp_tool.py (1)

133-134: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Avoid doing blocking network I/O directly inside _arun.

_arun() currently executes the synchronous SDK/requests path inline, so an async caller can block the event loop for up to timeout seconds per stamp. Offloading _run() to a worker thread keeps concurrent async tool calls responsive.

Suggested fix
+import asyncio
 import json
 import os
 from typing import Any
@@
     async def _arun(self, data: str, label: str | None = None, **kwargs: Any) -> str:
-        return self._run(data, label=label, **kwargs)
+        return await asyncio.to_thread(self._run, data, label=label, **kwargs)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@lib/crewai-tools/src/crewai_tools/tools/markovian_stamp_tool/markovian_stamp_tool.py`
around lines 133 - 134, The _arun implementation in MarkovianStampTool is
currently calling the synchronous _run path inline, which can block the event
loop for the duration of the network request. Update _arun to offload _run to a
worker thread so async callers stay responsive, and keep the existing data and
label arguments flowing through unchanged. Use the MarkovianStampTool._arun and
MarkovianStampTool._run methods as the fix points.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@lib/crewai-tools/src/crewai_tools/tools/markovian_stamp_tool/markovian_stamp_tool.py`:
- Around line 119-121: The Markovian stamp result handling assumes receipt is
always a mapping, but `_stamp()` can return a non-dict JSON value and then
`receipt.get()` raises outside the existing error flow. Update
`markovian_stamp_tool.py` in `MarkovianStampTool._stamp`/the receipt-processing
path to validate that `receipt` is a dict-like mapping before accessing
`merkle_root`; if it is not, return the same readable error string with the raw
receipt payload instead of letting an `AttributeError` escape.

In `@lib/crewai-tools/src/crewai_tools/tools/markovian_stamp_tool/README.md`:
- Around line 66-71: The fenced example output in the Markovian provenance
receipt section is missing a language label, which triggers markdown linting.
Update the unlabeled fence in the README example to use a text language tag so
the block is explicitly identified; the relevant content is the receipt snippet
under the markovian-provenance/v1 example.

In `@lib/crewai-tools/tests/tools/markovian_stamp_tool_test.py`:
- Around line 62-63: The test in markovian_stamp_tool_test should also verify
the HTTP response body returned by MarkovianStampTool._run, not just the failure
message and status code. Update the assertions around the result from _run to
include the expected exc.response.text content so the test covers the error
string built from the response body and catches regressions where the body is
dropped.
- Around line 17-23: The test named test_run_uses_sdk_when_available is
currently bypassing the SDK path by mocking MarkovianStampTool._stamp, so it
never verifies MarkovianClient integration. Update the test to inject a fake
markovian module, instantiate MarkovianStampTool, call run(data=...), and assert
the fake client’s stamp() method was invoked and its return value is used. Keep
the focus on the MarkovianStampTool and MarkovianClient symbols so the test
exercises the actual SDK branch.

---

Nitpick comments:
In
`@lib/crewai-tools/src/crewai_tools/tools/markovian_stamp_tool/markovian_stamp_tool.py`:
- Around line 133-134: The _arun implementation in MarkovianStampTool is
currently calling the synchronous _run path inline, which can block the event
loop for the duration of the network request. Update _arun to offload _run to a
worker thread so async callers stay responsive, and keep the existing data and
label arguments flowing through unchanged. Use the MarkovianStampTool._arun and
MarkovianStampTool._run methods as the fix points.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 212773a3-a9dc-454e-8922-41d1edce2864

📥 Commits

Reviewing files that changed from the base of the PR and between 2b87098 and f91cfbb.

📒 Files selected for processing (6)
  • lib/crewai-tools/src/crewai_tools/__init__.py
  • lib/crewai-tools/src/crewai_tools/tools/__init__.py
  • lib/crewai-tools/src/crewai_tools/tools/markovian_stamp_tool/README.md
  • lib/crewai-tools/src/crewai_tools/tools/markovian_stamp_tool/__init__.py
  • lib/crewai-tools/src/crewai_tools/tools/markovian_stamp_tool/markovian_stamp_tool.py
  • lib/crewai-tools/tests/tools/markovian_stamp_tool_test.py

Comment thread lib/crewai-tools/src/crewai_tools/tools/markovian_stamp_tool/README.md Outdated
Comment thread lib/crewai-tools/tests/tools/markovian_stamp_tool_test.py Outdated
Comment thread lib/crewai-tools/tests/tools/markovian_stamp_tool_test.py
@MarkovianProtocol

Copy link
Copy Markdown
Author

Thanks for the review. All four items are addressed in 95c90ac:

  1. _run now guards with isinstance(receipt, dict) and returns a readable error string before any .get(), so a list/string/null response can no longer raise an AttributeError outside the try block.
  2. README example-output fence now uses ```text (MD040).
  3. The "uses SDK" test now seeds a fake markovian module via sys.modules and asserts MarkovianClient().stamp(...) was called with the data, so the real import/call path is exercised instead of patching _stamp.
  4. The error-path test now also asserts the HTTP response body (boom) appears in the returned string. Added a dedicated non-dict-response test as well.

Verified locally: ruff check and ruff format --check clean on the tool, and pytest tests/tools/markovian_stamp_tool_test.py passes (5 passed).

@MarkovianProtocol

Copy link
Copy Markdown
Author

Thanks for the review. All four items are addressed on the current branch:

  • Non-dict receipts are guarded before .get(): _run checks isinstance(receipt, dict) and returns a readable error string instead of raising AttributeError.
  • The SDK test now seeds a fake markovian module into sys.modules and asserts MarkovianClient was constructed and stamp() was called, rather than mocking _stamp, so it actually exercises the SDK branch.
  • The HTTP-error test asserts the response body (boom) as well as the status code.
  • The README example-output fence is labeled text (MD040).

Ready for another look.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant