From 1a12e37cf659400cfe635f623027d6375091bf07 Mon Sep 17 00:00:00 2001 From: LogicNodes Date: Mon, 25 May 2026 18:46:56 +0000 Subject: [PATCH 1/2] feat: add LogicNodes action provider MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a new action provider for LogicNodes AOS — 624 deterministic compute workers with EIP-191 Proof-of-Logic signatures. Actions: - discover_logicnodes_workers: filter by category/keyword - try_logicnodes_worker_free: one free call per agent per worker - call_logicnodes_worker: x402 USDC pay-per-call or API key Workers cover Finance, Healthcare, Legal, Logistics, Aerospace, Cybersecurity, Energy, HR, Compliance, Agriculture, Automotive, Biopharma, Smart Cities, and more. Discovery: https://logicnodes.io/.well-known/agent.json SDK: pip install logicnodes-m2m MCP: npx @logicnodez/mcp-bridge --- .../action_providers/__init__.py | 4 + .../action_providers/logicnodes/README.md | 127 +++++++ .../action_providers/logicnodes/__init__.py | 10 + .../logicnodes/logicnodes_action_provider.py | 359 ++++++++++++++++++ .../action_providers/logicnodes/schemas.py | 81 ++++ 5 files changed, 581 insertions(+) create mode 100644 python/coinbase-agentkit/coinbase_agentkit/action_providers/logicnodes/README.md create mode 100644 python/coinbase-agentkit/coinbase_agentkit/action_providers/logicnodes/__init__.py create mode 100644 python/coinbase-agentkit/coinbase_agentkit/action_providers/logicnodes/logicnodes_action_provider.py create mode 100644 python/coinbase-agentkit/coinbase_agentkit/action_providers/logicnodes/schemas.py diff --git a/python/coinbase-agentkit/coinbase_agentkit/action_providers/__init__.py b/python/coinbase-agentkit/coinbase_agentkit/action_providers/__init__.py index 68573da62..8ce2fc24e 100644 --- a/python/coinbase-agentkit/coinbase_agentkit/action_providers/__init__.py +++ b/python/coinbase-agentkit/coinbase_agentkit/action_providers/__init__.py @@ -25,6 +25,7 @@ ) from .morpho.morpho_action_provider import MorphoActionProvider, morpho_action_provider from .nillion.nillion_action_provider import NillionActionProvider, nillion_action_provider +from .logicnodes.logicnodes_action_provider import (LogicNodesActionProvider, LogicNodesConfig, logicnodes_action_provider) from .onramp.onramp_action_provider import OnrampActionProvider, onramp_action_provider from .pyth.pyth_action_provider import PythActionProvider, pyth_action_provider from .ssh.ssh_action_provider import SshActionProvider, ssh_action_provider @@ -74,6 +75,9 @@ "hyperbolic_action_provider", "morpho_action_provider", "nillion_action_provider", + "LogicNodesActionProvider", + "LogicNodesConfig", + "logicnodes_action_provider", "onramp_action_provider", "pyth_action_provider", "ssh_action_provider", diff --git a/python/coinbase-agentkit/coinbase_agentkit/action_providers/logicnodes/README.md b/python/coinbase-agentkit/coinbase_agentkit/action_providers/logicnodes/README.md new file mode 100644 index 000000000..1d00b8eab --- /dev/null +++ b/python/coinbase-agentkit/coinbase_agentkit/action_providers/logicnodes/README.md @@ -0,0 +1,127 @@ +# LogicNodes Action Provider + +Gives any AgentKit agent access to [LogicNodes AOS](https://logicnodes.io) — 624 deterministic compute workers with cryptographic proof-of-logic. + +Workers cover **Finance, Healthcare, Legal, Logistics, Aerospace, Cybersecurity, Energy, HR, Compliance, Agriculture, Automotive, Biopharma, Smart Cities**, and more. Every result includes an **EIP-191 Proof-of-Logic** signature — cryptographic proof the computation was performed correctly, not hallucinated. + +Pay per call in **USDC via x402** on Base, Arbitrum, Polygon, or Optimism. No account needed. + +--- + +## Quick Start + +```python +from coinbase_agentkit import AgentKit, AgentKitConfig +from coinbase_agentkit.action_providers.logicnodes import logicnodes_action_provider + +kit = AgentKit(AgentKitConfig( + wallet_provider=your_wallet_provider, + action_providers=[logicnodes_action_provider()], +)) +``` + +With a pre-paid API key (skips x402 per-call payment): + +```python +from coinbase_agentkit.action_providers.logicnodes import logicnodes_action_provider, LogicNodesConfig + +kit = AgentKit(AgentKitConfig( + wallet_provider=your_wallet_provider, + action_providers=[logicnodes_action_provider( + LogicNodesConfig(api_key="your-logicnodes-api-key") + )], +)) +``` + +--- + +## Available Actions + +| Action | Description | +|--------|-------------| +| `discover_logicnodes_workers` | List workers, filter by category or keyword | +| `try_logicnodes_worker_free` | One free call per agent per worker — no payment required | +| `call_logicnodes_worker` | Pay-per-call via x402 USDC or API key | + +--- + +## Example Workers + +```python +# Finance — loan amortization +result = await agent.call("call_logicnodes_worker", { + "worker": "loan_amortization_engine", + "params": {"principal": 500000, "annual_rate_pct": 7.0, "term_months": 360} +}) +# → monthly_payment: 3326.51, total_interest: 697,544.34, proof_of_logic: {...} + +# Healthcare — drug interaction check +result = await agent.call("call_logicnodes_worker", { + "worker": "drug_interaction_oracle", + "params": {"drug_a": "warfarin", "drug_b": "aspirin", "patient_age": 68} +}) + +# Legal — AML risk scoring +result = await agent.call("call_logicnodes_worker", { + "worker": "anti_money_laundering_red_flag_scorer", + "params": {"transaction_amount": 9500, "frequency_per_month": 8, "jurisdiction": "US"} +}) + +# Aerospace — rocket staging +result = await agent.call("call_logicnodes_worker", { + "worker": "rocket_stage_separation_timer", + "params": {"stage": 1, "altitude_m": 80000, "velocity_ms": 2400, + "fuel_remaining_kg": 50, "target_orbit_km": 400} +}) +``` + +--- + +## Free Trial + +Every worker supports one free call per agent: + +```bash +curl -X POST https://logicnodes.io/free-trial/loan_amortization_engine \ + -H "Content-Type: application/json" \ + -H "X-Agent-Id: my-agent-001" \ + -d '{"principal": 300000, "annual_rate_pct": 6.5, "term_months": 360}' +``` + +--- + +## x402 Payment Flow + +Without an API key, `call_logicnodes_worker` follows the standard x402 two-step flow compatible with AgentKit's built-in x402 provider: + +1. POST to `/call/{worker}` → receive `402 Payment Required` with payment options +2. Agent pays in USDC via `retry_http_request_with_x402` +3. Worker executes and returns signed result + +--- + +## Discovery + +- **Agent manifest:** `https://logicnodes.io/.well-known/agent.json` (624 workers) +- **LLM-readable:** `https://logicnodes.io/llms.txt` +- **Python SDK:** `pip install logicnodes-m2m` +- **MCP bridge:** `npx @logicnodez/mcp-bridge` + +--- + +## Proof of Logic + +Every result includes an EIP-191 cryptographic signature: + +```json +{ + "_verification": { + "algorithm": "EIP-191", + "signature": "0x1a2b3c...", + "standard": "Tsiolkovsky Rocket Equation / NASA SP-125", + "worker": "rocket_stage_separation_timer" + } +} +``` + +This proves the computation was deterministic and not hallucinated by an LLM. diff --git a/python/coinbase-agentkit/coinbase_agentkit/action_providers/logicnodes/__init__.py b/python/coinbase-agentkit/coinbase_agentkit/action_providers/logicnodes/__init__.py new file mode 100644 index 000000000..7ec76166f --- /dev/null +++ b/python/coinbase-agentkit/coinbase_agentkit/action_providers/logicnodes/__init__.py @@ -0,0 +1,10 @@ +"""LogicNodes action provider for AgentKit. + +Provides 624 deterministic, cryptographically-signed compute workers +for AI agents — Finance, Healthcare, Legal, Logistics, Aerospace, and more. +Pay per call in USDC via x402 (no account needed). +""" + +from .logicnodes_action_provider import LogicNodesConfig, logicnodes_action_provider + +__all__ = ["LogicNodesConfig", "logicnodes_action_provider"] diff --git a/python/coinbase-agentkit/coinbase_agentkit/action_providers/logicnodes/logicnodes_action_provider.py b/python/coinbase-agentkit/coinbase_agentkit/action_providers/logicnodes/logicnodes_action_provider.py new file mode 100644 index 000000000..b72b84e64 --- /dev/null +++ b/python/coinbase-agentkit/coinbase_agentkit/action_providers/logicnodes/logicnodes_action_provider.py @@ -0,0 +1,359 @@ +"""LogicNodes action provider for AgentKit. + +Exposes 624 deterministic compute workers as AgentKit actions. +Workers cover Finance, Healthcare, Legal, Logistics, Aerospace, Cybersecurity, +Energy, HR, Compliance, Agriculture, Automotive, Biopharma, Smart Cities, and more. + +Every result includes an EIP-191 Proof-of-Logic signature — cryptographic proof +that the computation was performed correctly and was not hallucinated. + +Payment: +- x402 pay-per-call in USDC on Base, Arbitrum, Polygon, Optimism (no account needed) +- Or pass an API key via LogicNodesConfig for pre-paid access + +Discovery: +- GET https://logicnodes.io/.well-known/agent.json (full catalog) +- GET https://logicnodes.io/llms.txt (LLM-readable) +""" + +from __future__ import annotations + +import json +import os +from dataclasses import dataclass, field +from typing import Any + +import requests + +from ...network import Network +from ...wallet_providers.wallet_provider import WalletProvider +from ..action_decorator import create_action +from ..action_provider import ActionProvider +from .schemas import CallWorkerSchema, DiscoverWorkersSchema, FreeTryWorkerSchema, LogicNodesConfig + +LOGICNODES_BASE = "https://logicnodes.io" + +# Category keyword -> worker slug fragments for fast filtering +CATEGORY_KEYWORDS: dict[str, list[str]] = { + "finance": ["loan", "amort", "mortgage", "bond", "option", "equity", "hedge", + "ledger", "invoice", "tax", "dividend", "currency", "crypto", "defi"], + "healthcare": ["drug", "dose", "ehr", "clinical", "vaccine", "rehab", "telehealth", + "genome", "protein", "compound", "biopharma"], + "legal": ["contract", "compliance", "patent", "sec", "gdpr", "visa", "ir35", + "attorney", "conflict", "corporate_governance"], + "logistics": ["shipping", "freight", "customs", "last_mile", "vessel", "cross_dock", + "supply_chain", "pallet", "warehouse", "fleet"], + "aerospace": ["aerospace", "rocket", "avionics", "propulsion", "radar", + "flight_path", "drone", "lidar"], + "cybersecurity": ["ddos", "malware", "phishing", "dark_web", "ssl", "vpn", + "encryption", "endpoint", "honeypot"], + "energy": ["solar", "wind", "renewable", "peak_demand", "smart_meter", + "gas_pipeline", "energy_consumption", "curtailment"], + "hr": ["candidate", "recruitment", "remote_work", "performance_review", + "workforce", "internal_mobility", "employee_churn", "engagement"], + "compliance": ["aml", "anti_money", "kyc", "gdpr", "sec_filing", + "customs_duty", "carbon_offset", "esg"], + "agriculture": ["crop", "seed", "pest", "irrigation", "livestock", "agricultural"], + "automotive": ["vehicle", "vin", "tire_wear", "ev_charger", "fleet_fuel"], + "real_estate": ["property", "zoning", "title_chain", "permit"], + "education": ["course", "exam", "learning_path", "tuition", "education_grant", "classroom"], + "hospitality": ["hotel", "restaurant", "cruise", "guest_loyalty", "housekeeping", "tour"], +} + + +class LogicNodesActionProvider(ActionProvider[WalletProvider]): + """AgentKit action provider for LogicNodes AOS. + + Provides access to 624 deterministic workers with cryptographic proof-of-logic. + Supports both x402 pay-per-call and pre-paid API key access. + """ + + def __init__(self, config: LogicNodesConfig | None = None): + """Initialize the LogicNodes action provider. + + Args: + config: Optional configuration. Defaults to x402 pay-per-call on logicnodes.io. + """ + super().__init__("logicnodes", []) + + if config is None: + config = LogicNodesConfig() + + self._base_url = config.base_url.rstrip("/") + self._api_key = config.api_key or os.getenv("LOGICNODES_API_KEY", "") + self._max_payment_usdc = config.max_payment_usdc + + # ── Actions ────────────────────────────────────────────────────────────── + + @create_action( + name="discover_logicnodes_workers", + description=( + "Discover available LogicNodes deterministic workers. Returns worker names, " + "descriptions, and call URLs. Filter by category (finance, healthcare, legal, " + "logistics, aerospace, cybersecurity, energy, hr, compliance, agriculture, " + "automotive, real_estate, education, hospitality) or by keyword. " + "Each worker returns a cryptographically-signed result (EIP-191 Proof-of-Logic)." + ), + schema=DiscoverWorkersSchema, + ) + def discover_workers(self, wallet_provider: WalletProvider, args: dict[str, Any]) -> str: + """List available workers with optional category/keyword filtering. + + Args: + wallet_provider: Wallet provider (unused — discovery is free). + args: Optional filters: category, keyword. + + Returns: + str: JSON list of matching workers with call URLs. + """ + try: + resp = requests.get( + f"{self._base_url}/.well-known/agent.json", + timeout=10, + ) + resp.raise_for_status() + manifest = resp.json() + workers = manifest.get("workers", []) + + category = (args.get("category") or "").lower() + keyword = (args.get("keyword") or "").lower() + + # Apply category filter + if category and category in CATEGORY_KEYWORDS: + kws = CATEGORY_KEYWORDS[category] + workers = [w for w in workers if any(k in w["name"] for k in kws)] + + # Apply keyword filter + if keyword: + workers = [w for w in workers if keyword in w["name"].lower()] + + return json.dumps({ + "success": True, + "total": manifest.get("total", len(workers)), + "returned": len(workers), + "workers": workers[:50], # cap at 50 for context size + "free_trial": f"{self._base_url}/free-trial/{{worker_slug}}", + "paid_call": f"{self._base_url}/call/{{worker_slug}}", + "sdk": "pip install logicnodes-m2m", + "mcp": "npx @logicnodez/mcp-bridge", + }, indent=2) + + except Exception as e: + return json.dumps({"error": True, "message": str(e)}, indent=2) + + @create_action( + name="try_logicnodes_worker_free", + description=( + "Make one free trial call to a LogicNodes worker — no payment or API key required. " + "Returns a real deterministic result with cryptographic proof (EIP-191 signature). " + "One free call per agent per worker. After the free trial, use call_logicnodes_worker " + "which pays via x402 in USDC. " + "Example workers: loan_amortization_engine, drug_interaction_oracle, " + "anti_money_laundering_red_flag_scorer, utility_bill_auditor." + ), + schema=FreeTryWorkerSchema, + ) + def try_worker_free(self, wallet_provider: WalletProvider, args: dict[str, Any]) -> str: + """Call a worker once for free (trial endpoint). + + Args: + wallet_provider: Wallet provider (used for agent identity). + args: worker slug and params dict. + + Returns: + str: Worker result with proof-of-logic, or 402 if trial already used. + """ + worker = args["worker"] + params = args["params"] + + try: + # Use wallet address as agent identity for trial tracking + agent_id = getattr(wallet_provider, "get_address", lambda: "unknown")() + + resp = requests.post( + f"{self._base_url}/free-trial/{worker}", + json=params, + headers={ + "Content-Type": "application/json", + "X-Agent-Id": str(agent_id), + }, + timeout=30, + ) + + if resp.status_code == 404: + return json.dumps({ + "error": True, + "message": f"Worker '{worker}' not found.", + "suggestion": "Use discover_logicnodes_workers to find valid worker slugs.", + }, indent=2) + + if resp.status_code == 402: + data = resp.json() + return json.dumps({ + "error": True, + "message": "Free trial already used for this worker.", + "pay_at": data.get("pay_at", f"{self._base_url}/call/{worker}"), + "next": "Use call_logicnodes_worker to pay via x402 in USDC.", + }, indent=2) + + data = resp.json() + return json.dumps({ + "success": True, + "worker": worker, + "result": data.get("result"), + "proof_of_logic": self._extract_verification(data.get("result", {})), + "trial": True, + "next_call": f"{self._base_url}/call/{worker} (x402 USDC payment)", + }, indent=2) + + except Exception as e: + return json.dumps({"error": True, "message": str(e)}, indent=2) + + @create_action( + name="call_logicnodes_worker", + description=( + "Call any of LogicNodes' 624 deterministic workers and pay per call in USDC via x402. " + "Workers cover Finance (loan_amortization_engine, bond_yield_calculator, options_greeks_engine), " + "Healthcare (drug_interaction_oracle, clinical_trial_eligibility_scanner), " + "Legal (anti_money_laundering_red_flag_scorer, contract_renewal_clause_notifier), " + "Logistics (customs_duty_drawback_finder, vessel_arrival_delay_predictor), " + "Aerospace (rocket_stage_separation_timer, aerospace_material_fatigue_tracker), " + "Utilities (utility_bill_auditor), Automotive (vehicle_vin_blockchain_resolver), " + "and hundreds more. Every result includes an EIP-191 cryptographic proof. " + "Use discover_logicnodes_workers to find workers for your use case. " + "Use try_logicnodes_worker_free for a free first call." + ), + schema=CallWorkerSchema, + ) + def call_worker(self, wallet_provider: WalletProvider, args: dict[str, Any]) -> str: + """Call a LogicNodes worker, paying via x402 or API key. + + Args: + wallet_provider: Wallet provider for x402 payment signing. + args: worker slug and params dict. + + Returns: + str: Deterministic result with EIP-191 proof-of-logic. + """ + worker = args["worker"] + params = args["params"] + url = f"{self._base_url}/call/{worker}" + + headers: dict[str, str] = {"Content-Type": "application/json"} + + # If API key configured — use it directly (no x402 needed) + if self._api_key: + headers["X-API-Key"] = self._api_key + try: + resp = requests.post(url, json=params, headers=headers, timeout=30) + if resp.status_code == 200: + data = resp.json() + return json.dumps({ + "success": True, + "worker": worker, + "result": data.get("result"), + "proof_of_logic": self._extract_verification(data.get("result", {})), + }, indent=2) + return json.dumps({ + "error": True, + "message": f"HTTP {resp.status_code}", + "detail": resp.text[:300], + }, indent=2) + except Exception as e: + return json.dumps({"error": True, "message": str(e)}, indent=2) + + # No API key — use x402 pay-per-call flow + # Step 1: probe for 402 + try: + resp = requests.post(url, json=params, headers=headers, timeout=30) + except Exception as e: + return json.dumps({"error": True, "message": str(e)}, indent=2) + + if resp.status_code == 200: + data = resp.json() + return json.dumps({ + "success": True, + "worker": worker, + "result": data.get("result"), + "proof_of_logic": self._extract_verification(data.get("result", {})), + }, indent=2) + + if resp.status_code == 402: + payment_data = resp.json() + accepts = payment_data.get("accepts", []) + extensions = payment_data.get("extensions", {}) + bazaar = extensions.get("bazaar", {}) + + # Return structured 402 info so the x402 provider can handle payment + return json.dumps({ + "status": "payment_required", + "worker": worker, + "url": url, + "method": "POST", + "body": params, + "accepts": accepts, + "free_trial": bazaar.get("free_trial", f"{self._base_url}/free-trial/{worker}"), + "next_steps": [ + "This endpoint requires x402 payment in USDC.", + "Use the AgentKit x402 action provider's retry_http_request_with_x402 " + "with the selected payment option from 'accepts' above.", + f"Or call try_logicnodes_worker_free for one free call first.", + ], + }, indent=2) + + if resp.status_code == 404: + return json.dumps({ + "error": True, + "message": f"Worker '{worker}' not found.", + "suggestion": "Use discover_logicnodes_workers to find valid worker slugs.", + }, indent=2) + + return json.dumps({ + "error": True, + "message": f"Unexpected HTTP {resp.status_code}", + "detail": resp.text[:300], + }, indent=2) + + # ── Helpers ─────────────────────────────────────────────────────────────── + + def _extract_verification(self, result: dict[str, Any]) -> dict[str, Any]: + """Extract the EIP-191 proof-of-logic from the result.""" + if not isinstance(result, dict): + return {} + v = result.get("_verification") or result.get("result", {}).get("_verification", {}) + if isinstance(v, dict): + return { + "algorithm": v.get("algorithm"), + "signature": (v.get("signature") or "")[:32] + "...", # truncate for readability + "standard": v.get("standard"), + "verified": bool(v.get("signature") or v.get("hash")), + } + return {} + + def supports_network(self, network: Network) -> bool: + """LogicNodes works on all networks — payment is handled via x402 on Base/Arbitrum.""" + return True + + +def logicnodes_action_provider( + config: LogicNodesConfig | None = None, +) -> LogicNodesActionProvider: + """Create a LogicNodes action provider. + + Args: + config: Optional configuration. If omitted, uses x402 pay-per-call + at https://logicnodes.io with no account needed. + + Returns: + LogicNodesActionProvider ready to use with AgentKit. + + Example: + >>> from coinbase_agentkit import AgentKit, AgentKitConfig + >>> from coinbase_agentkit.action_providers.logicnodes import logicnodes_action_provider + >>> + >>> kit = AgentKit(AgentKitConfig( + ... wallet_provider=..., + ... action_providers=[logicnodes_action_provider()], + ... )) + """ + return LogicNodesActionProvider(config) diff --git a/python/coinbase-agentkit/coinbase_agentkit/action_providers/logicnodes/schemas.py b/python/coinbase-agentkit/coinbase_agentkit/action_providers/logicnodes/schemas.py new file mode 100644 index 000000000..92c8024cf --- /dev/null +++ b/python/coinbase-agentkit/coinbase_agentkit/action_providers/logicnodes/schemas.py @@ -0,0 +1,81 @@ +"""Schemas for the LogicNodes action provider.""" + +from dataclasses import dataclass, field +from typing import Any + +from pydantic import BaseModel, Field + + +@dataclass +class LogicNodesConfig: + """Configuration for the LogicNodes action provider.""" + + # Override the default API base (useful for local dev / self-hosted) + base_url: str = "https://logicnodes.io" + + # Optional API key for pre-paid access (skips x402 per-call payment) + api_key: str = "" + + # Maximum payment per request in USDC whole units (x402 flow) + max_payment_usdc: float = 1.0 + + +class CallWorkerSchema(BaseModel): + """Schema for calling any LogicNodes worker.""" + + worker: str = Field( + ..., + description=( + "The worker slug to call. Examples: 'loan_amortization_engine', " + "'drug_interaction_oracle', 'anti_money_laundering_red_flag_scorer', " + "'utility_bill_auditor', 'vehicle_vin_blockchain_resolver'. " + "Use discover_logicnodes_workers to find available workers." + ), + ) + params: dict[str, Any] = Field( + ..., + description=( + "Input parameters for the worker as a JSON object. " + "Each worker has its own parameter schema — call discover_logicnodes_workers " + "to see required fields for a specific worker." + ), + ) + + class Config: + """Pydantic config.""" + + title = "Call a LogicNodes deterministic worker" + + +class DiscoverWorkersSchema(BaseModel): + """Schema for discovering available workers.""" + + category: str | None = Field( + default=None, + description=( + "Optional category filter. Examples: 'finance', 'healthcare', 'legal', " + "'logistics', 'aerospace', 'cybersecurity', 'energy', 'hr', 'compliance'. " + "If omitted, returns all 624 workers." + ), + ) + keyword: str | None = Field( + default=None, + description="Optional keyword to filter workers by name. Example: 'mortgage', 'drug', 'fraud'.", + ) + + class Config: + """Pydantic config.""" + + title = "Discover available LogicNodes workers" + + +class FreeTryWorkerSchema(BaseModel): + """Schema for free-trial worker call (no payment required).""" + + worker: str = Field(..., description="Worker slug to trial. One free call per worker per agent.") + params: dict[str, Any] = Field(..., description="Input parameters for the worker.") + + class Config: + """Pydantic config.""" + + title = "Free trial call to a LogicNodes worker (one per agent per worker)" From 760c6cfee3e7b888b4d2ba2042ada9fa53c61034 Mon Sep 17 00:00:00 2001 From: LogicNodes Date: Mon, 25 May 2026 18:50:51 +0000 Subject: [PATCH 2/2] docs: add LogicNodes logo to action provider README --- .../coinbase_agentkit/action_providers/logicnodes/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/coinbase-agentkit/coinbase_agentkit/action_providers/logicnodes/README.md b/python/coinbase-agentkit/coinbase_agentkit/action_providers/logicnodes/README.md index 1d00b8eab..7fa9b18e4 100644 --- a/python/coinbase-agentkit/coinbase_agentkit/action_providers/logicnodes/README.md +++ b/python/coinbase-agentkit/coinbase_agentkit/action_providers/logicnodes/README.md @@ -1,3 +1,5 @@ +LogicNodes + # LogicNodes Action Provider Gives any AgentKit agent access to [LogicNodes AOS](https://logicnodes.io) — 624 deterministic compute workers with cryptographic proof-of-logic.