OPEN BETA v0.1 - star, share, and provide feedback :)
Python bindings for the Kinic CLI core, enabling you to build AI agents with verifiable, owned memory on the Internet Computer. Give your agents the memory they can prove, own, and carry anywhere.
For the wizards building trustless agents - no more lobotomized summons that reset on every quest.
Looking for the docs? See docs/cli.md for the command-line interface and docs/tui.md for the terminal UI.
Made with ❤️ by ICME Labs.
Traditional AI agents face three critical problems:
- Memory Without Proof: TEEs prove computation, but can't verify the memories your agent retrieved were correct.
- Memory Without Ownership: Your agent's identity is onchain, but its memories live in Pinecone, Weaviate, or other centralized providers.
- Payment Without Verification: With x402, agents can pay for memory retrieval - but can't prove they received the right results.
Kinic solves this with zkTAM (zero-knowledge Trustless Agentic Memory):
- ✅ Verifiable: zkML proofs for embeddings - no black box vectors
- ✅ Owned: Your memory lives on-chain in WASM canisters you control
- ✅ Portable: Move your agent's memory between any infrastructure
By default we use the Internet Computer as the DA layer—with VetKey encryption and cross-chain signing (tECDSA). You can run it locally or on any WASM-based DA layer. In future versions, full zkML support will be enabled, allowing for trustless verification on nearly all blockchains.
- dfx 0.31+
- dfx identity: Create or select a named identity with
dfx identity new <name>ordfx identity use <name> - KINIC tokens: Have KINIC ready if you plan to create memories
- yazi: Required only if you want to use the file chooser in TUI
Filemode - pdftotext: Required only if you want to insert PDFs
Note: Do not use the
defaultidentity withkinic-cli—it always fails. Use a named identity instead.
On macOS, the PEM for the dfx identity you use with --identity must be stored in Keychain.
When using a local environment, make sure the local replica and supporting canisters are already running.
Optional local setup: if you need local launcher, ledger, or II canisters, run ./scripts/setup.sh after dfx start --clean --background.
Kinic TUI is a terminal UI for operating Kinic memory canisters. It lets you handle list, search, create, insert, and settings changes from one screen, so you do not need to remember every subcommand each time.
Follow this flow once from start to finish:
- Start the TUI
- Confirm your identity and balance
- Create one memory
- Insert a short string
- Search for that content
Operate Kinic memories from one terminal screen. Create a memory, insert text or files, search for content, and use chat without leaving the UI.
Kinic TUI is included in kinic-cli. For OSS users, the usual path is to download a release binary and run it directly, or start it from source during development.
Mainnet:
kinic-cli --identity alice --ic tuiLocal replica:
kinic-cli --identity alice tuiFrom source:
cargo run -- --identity alice --ic tuiFirst-run notes:
--identityis required--iiis not supported yet- on macOS, you may be asked to allow Keychain access
- the TUI opens on the
Memoriestab first Filemode requiresyazifor the chooser, but manual path input still works without it
Install yazi on macOS:
brew install yaziIf you also want to try PDF insertion:
brew install poppler- Start the TUI
- In
Settings, confirmPrincipal IDandKINIC balance - In
Create, create one memory - In
Insert, add a short string - In
Memories, search for that string
For the fastest first success, start with Inline Text. It avoids file chooser and PDF conversion setup.
When the TUI starts, it opens on the Memories tab. Use 1 to 5 to switch tabs, Tab / Shift+Tab to move focus, and ? to open help. In normal list navigation, q quits and Ctrl+R refreshes the current view.
What to understand first:
Memories: list, search, detail view, and chatInsert: add files, text, or manual embeddingsCreate: create a new memoryMarket: reserved and not implemented yetSettings: principal, balance, default memory, saved tags, and retrieval settings
Open Settings and confirm that Principal ID matches the identity you launched with. Then check whether KINIC balance is high enough to create a memory. If needed, you can transfer tokens from the transfer modal, and Ctrl+R refreshes both Principal ID and KINIC balance.
Quick checklist:
- Open
Settings - Read
Principal ID - Confirm
Identity name - Confirm
Network - Press
Ctrl+Rif the balance looks stale
Main items shown in this tab:
Principal IDKINIC balanceDefault memorySaved tagsEmbedding API endpointIdentity nameAuth modeNetwork
Move to Create, enter a short name and description, and submit. This screen also shows the current principal, current balance, and required creation cost, so you can catch funding issues before submission. If the balance is insufficient or retrieval fails, a message appears immediately.
Walkthrough:
- Press
3orCtrl+Nto openCreate - Enter
Name - Enter
Description - Move to
Submitand pressEnter - Return to
Memoriesand confirm that the new memory appears in the list
For the first run, Inline Text is the easiest choice. It avoids file chooser setup and PDF conversion. Inline Text supports multiple lines and works well for short notes or test data.
Walkthrough:
- Open
Insert - Set
ModetoInline Text - Leave
Memory IDempty if you already set a default memory, or paste the memory id if you did not - Enter a simple
Tag, for examplehello - Enter a short unique string that will be easy to search for
- Submit
Shared fields in the Insert tab:
Mode: insertion methodMemory ID: target memoryTag: tag to save with the contentSubmit: run the insertion
Notes:
- if
Memory IDis empty and a default memory is already set, that value appears as a placeholder candidate Filemode supportsmd,markdown,mdx,txt,json,yaml,yml,csv,log, andpdfManual Embeddingmode acceptsTextplus anEmbeddingin JSON array format
Example text:
Kinic TUI smoke test: mango-orbit-314
File mode:
- open the picker with
yazi, or type the path directly - a good second step after inline text
- manual
FilePathinput still works even ifyaziis not installed
PDF mode:
- PDFs are converted to Markdown before insertion
pdftotextis required- PDF insertion fails if
pdftotextis not available
Return to Memories, select the target memory, switch the search scope to selected memory, and search for the unique text you just inserted. Press Enter to open the result details, and Esc to return to the list.
Walkthrough:
- Open
Memories - Select the memory you just created
- Set the scope to
selected memory - Search for the exact text you inserted
- Press
Enteron the result to open the details
Notes:
- switch search scope with
←→ all memoriessearches across every memoryselected memorysearches only within the currently selected memory- if you want to search inside one memory, it is easiest to select that memory first and then search
After you confirm search works, you can try chat from the Memories tab. Press Shift+C to open the chat panel. Start with the selected memory, then switch to all memories if needed. Press Shift+N to start a new empty thread for the current chat context.
Current behavior:
- chat can target either the selected memory or all searchable memories
- the TUI restores the last used thread for each selected memory and for
all memories - v1 does not have a thread list yet, so you cannot reopen older threads from the UI
- existing saved chat history is not migrated; the TUI starts from the new thread store file
| Key | Action |
|---|---|
1 to 5 |
Switch tabs |
Tab / Shift+Tab |
Move focus |
↑ / ↓ |
Move through lists and fields |
Enter |
Open, confirm, submit |
Esc |
Go back or close |
? |
Show help |
q |
Quit |
Ctrl+N |
Open Create |
Ctrl+R |
Refresh the current view |
Shift+C |
Toggle the chat panel |
Shift+D |
Set the selected memory as default |
- set a default memory
- insert a file
- insert a PDF
- reuse saved tags
- rename a memory
- add an existing memory canister
- tune chat retrieval settings
For more detail, see docs/tui.md.
If you want to work directly with Kinic from the command line or from Python, use the setup below instead of the TUI flow. This path is useful when you want to script memory operations, integrate Kinic into an agent, or call the library from your own application.
From PyPI:
pip install kinic-py
# Or with uv
uv pip install kinic-pyFrom source:
Requires Rust toolchain for the PyO3 extension.
pip install -e .
# Or with uv
uv pip install -e .Create or switch to a named dfx identity before using the CLI or Python library:
dfx identity new <name>
# or if you have already created it
dfx identity use <name>Make sure you have at least 1 KINIC token:
# Get your principal
dfx --identity <name> identity get-principal
# Check balance (result is in base units: 100000000 = 1 KINIC)
dfx canister --ic call 73mez-iiaaa-aaaaq-aaasq-cai icrc1_balance_of '(record {owner = principal "<your principal>"; subaccount = null; }, )'
# Example: (100000000 : nat) == 1 KINICDM https://x.com/wyatt_benno for KINIC prod tokens with your principal ID.
Or purchase them from MEXC or swap at https://app.icpswap.com/ .
If you prefer browser login instead of a Keychain-backed dfx identity:
cargo run -- --ii login
cargo run -- --ii listDelegations are stored at ~/.config/kinic/identity.json with a default TTL of 6 hours.
The login flow uses a local callback on port 8620.
from kinic_py import KinicMemories
km = KinicMemories("<identity name>") # use ic=True for mainnet, e.g. KinicMemories("<name>", ic=True)
memory_id = km.create("Python demo", "Created via kinic_py")
tag = "notes"
markdown = "# Hello Kinic!\n\nInserted from Python."
km.insert_markdown(memory_id, tag, markdown)
for score, payload in km.search(memory_id, "Hello"):
print(f"{score:.4f} -> {payload}")You can tag inserted content such as notes or summary_q1 and manage it later by tag.
Python (preferred: insert_pdf_file):
num_chunks = km.insert_pdf_file(memory_id, "quarterly_report", "./docs/report.pdf")
print(f"Inserted {num_chunks} PDF chunks")The deprecated insert_pdf(...) alias still works, but insert_pdf_file(...) is the canonical API.
See python/examples/insert_pdf_file.py for a runnable script.
Runs a search and prepares context for an AI answer. The CLI calls /chat at EMBEDDING_API_ENDPOINT (default https://api.kinic.io) and prints only the <answer> text.
prompt, answer = km.ask_ai(memory_id, "What did we say about quarterly goals?", top_k=3, language="en")
print("Prompt:\n", prompt)
print("Answer:\n", answer)km.ask_aireturns(prompt, answer)whereansweris the<answer>section from the chat response.- CLI usage:
cargo run -- --identity <name> ask-ai --memory-id <id> --query "<q>" --top-k 3
You can control who can read or write a memory canister—either everyone (anonymous) or specific principals—and assign reader or writer roles.
Python example:
from kinic_py import KinicMemories
km = KinicMemories("<identity>")
# Grant reader access to everyone (anonymous)
km.add_user("<memory canister id>", "anonymous", "reader")
# Grant writer access to a specific principal
km.add_user("<memory canister id>", "w7x7r-cok77-7x4qo-hqaaa-aaaaa-b", "writer")CLI example:
# Give everyone reader access
cargo run -- --identity <name> config \
--memory-id <memory canister id> \
--add-user anonymous reader
# Grant writer access to a specific principal
cargo run -- --identity <name> config \
--memory-id <memory canister id> \
--add-user w7x7r-cok77-7x4qo-hqaaa-aaaaa-b writerNotes:
anonymousapplies to everyone; admin cannot be granted to anonymous.- Roles:
admin(1),writer(2),reader(3). - Principals are validated; invalid text fails fast.
Trigger the launcher’s update_instance for a given memory id:
cargo run -- --identity <name> update \
--memory-id <memory canister id>Query the ledger for the current identity’s balance (base units):
cargo run -- --identity <name> balanceStateful helper that mirrors the CLI behavior.
KinicMemories(identity: str, ic: bool = False)Parameters:
identity: Your dfx identity nameic: SetTrueto target mainnet (default:Falsefor local)
Deploy a new memory canister.
Returns: Canister principal (memory_id)
List all memory canisters owned by your identity.
Embed and store markdown text with zkML verification.
Returns: Number of chunks inserted
Embed and store markdown from a file.
Returns: Number of chunks inserted
Convert a PDF to markdown and insert it.
Returns: Number of chunks inserted
Search memories with semantic similarity.
Returns: List of (score, payload) tuples sorted by relevance
ask_ai(memory_id: str, query: str, top_k: int | None = None, language: str | None = None) -> Tuple[str, str]
Run the Ask AI flow: search, build an LLM prompt, and return (prompt, answer) where answer is the <answer> section from the chat endpoint.
Parameters: top_k (defaults to 5), language code (e.g., "en")
Return the current identity’s balance as (base_units, kinic).
Trigger update_instance via the launcher for the given memory canister.
Stateless alternatives available:
create_memory(identity, name, description, ic=False)list_memories(identity, ic=False)insert_markdown(identity, memory_id, tag, text, ic=False)insert_markdown_file(identity, memory_id, tag, path, ic=False)insert_pdf_file(identity, memory_id, tag, path, ic=False)insert_pdf(identity, memory_id, tag, path, ic=False)search_memories(identity, memory_id, query, ic=False)ask_ai(identity, memory_id, query, top_k=None, language=None, ic=False)get_balance(identity, ic=False)update_instance(identity, memory_id, ic=False)
Run the complete example at python/examples/memories_demo.py:
# With existing memory
uv run python python/examples/memories_demo.py \
--identity <name> \
--memory-id <memory canister id>
# Deploy new memory
uv run python python/examples/memories_demo.py --identity <name>
# Use mainnet
uv run python python/examples/memories_demo.py --identity <name> --icAsk AI example at python/examples/ask_ai.py:
uv run python python/examples/ask_ai.py \
--identity <name> \
--memory-id <memory canister id> \
--query "What is xxxx?" \
--top-k 3Build agents with verifiable memory that works with the ERC-8004 trust model:
km = KinicMemories("agent-identity", ic=True)
memory_id = km.create("Trading Agent Memory", "Market analysis and decisions")
# Store verified context
km.insert_markdown(memory_id, "analysis", market_report)
# Retrieve with proof
results = km.search(memory_id, "BTC trend analysis")Agents can pay for memory operations with verifiable results:
# Agent pays for retrieval via x402
# Memory operations return zkML proofs
# Agent can verify it received correct embeddings for paymentSee docs/python-wheel.md for packaging, testing, and PyPI upload instructions.
Ready to deploy on mainnet? DM https://x.com/wyatt_benno for KINIC prod tokens and start building agents with trustless memory.
- Blog Post: Trustless AI can't work without Trustless AI Memory
- Vectune: WASM-based vector database
- JOLT Atlas: zkML framework for embedding verification
Built by wizards, for wizards. 🧙♂️✨
Stop building lobotomized agents. Start building with memory they can prove.



