knotwork

mcp
Security Audit
Fail
Health Warn
  • License — License: Apache-2.0
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 5 GitHub stars
Code Fail
  • rm -rf — Recursive force deletion command in .github/scripts/run-instrumented-selftest.sh
Permissions Pass
  • Permissions — No dangerous permissions requested

No AI report is available for this listing yet.

SUMMARY

An AI agent you build, not just prompt. Local-first Android agent with on-device inference (LiteRT-LM), pipelines you assemble yourself, MCP tool calling, and your confirmation before any risky action.

README.md

Knotwork — on-device AI agent for Android

Check
Instrumented
License: Apache 2.0
Version
Android API
Google Play

An AI agent you build, not just prompt. A local-first Android agent whose
behaviour you assemble from explicit, verifiable blocks — and every risky
action waits for your confirmation. It plans and acts across your phone, and a
typical conversation never leaves the device.

Sharing a page into Knotwork: the Share Handler pipeline runs on-device and captures it to the workspace inbox

What it is

Knotwork is an autonomous assistant that takes a request in plain language,
decides what to do, and carries the work out across your Android device.
Inference runs on-device via LiteRT-LM
(Google Edge AI, the successor to TensorFlow Lite), so planning, tool calls,
and replies stay on the phone unless you deliberately reach for a cloud model.

What makes it Knotwork rather than another chat box is that you build the
behaviour
. Every conversation is processed by a pipeline — what Tasker, n8n,
or Zapier would call a workflow: a graph of typed nodes (input, on-device LLM,
optional cloud LLM, tool calls, routing, decomposition, evaluation,
clarifications, output) that you can edit inside the app or in a standalone
browser editor. Automations that can act on their own still can't act
unsupervised: destructive or sensitive tool calls pass through a
human-in-the-loop gate, so the agent never sends a message or writes a file
without showing you the request first.

Who it's for

Knotwork is built for the technically literate flagship-Android owner who
values privacy as a practice rather than a slogan, enjoys constructing the way
their tools behave, and is already at home in the world of Tasker, Obsidian,
Home Assistant, or r/LocalLLaMA. If you want to know — and control — exactly
what your agent does with your data, this is for you.

It is deliberately not a mass-market "ask a question, get an answer"
assistant. For that, Gemini is free and built into the OS, and competing there
is a losing bet regardless of code quality. Knotwork trades that convenience for
control, transparency, and local-first data handling.

See it work

The Share Handler scenario is a good one-glance picture of the whole idea:
share an article, a message, or a screenshot to Knotwork from any app, and an
on-device model turns it into a clean, structured note in your inbox — pausing
to ask before it writes the file. On-device inference, a real tool call, and the
human-in-the-loop gate, all in one flow.

First launch leads with what the agent should do for you rather than an empty
canvas: pick a ready-made scenario and Knotwork materialises its pipeline as
your default, wires any surface it uses, and downloads exactly the model that
scenario needs — with size and live progress — before dropping you into a
working chat. A Start from scratch path stays one tap away.

https://github.com/user-attachments/assets/2ea06de5-6832-4e0c-ad48-430f375d8b72

The hero above is a real on-device capture — no mockups.

Highlights

  • Runs on your device. On-device LLM inference through LiteRT-LM, with
    optional NPU/GPU acceleration; CPU-only works too, just slower. Cloud
    providers (OpenAI, Anthropic, Google Gemini, DeepSeek, Ollama) are optional,
    opt-in, and bring-your-own-key — nothing leaves the device unless you
    configure it to.
  • You build the pipeline. A drag-and-drop editor with pan / pinch-zoom,
    snap-to-grid, a radial node picker, auto-layout, inline validation, run-trace
    overlay, and per-type configuration for all 14 node types — plus a standalone
    browser editor for authoring pipelines without
    launching the app. Prompt variables ($DATE, $TIME, $TOOLS, $MODEL,
    $MEMORY_SUMMARY, $LANG, $LOCATION, $USER, $DEVICE) render fresh on
    every run. Prompts import and export as Markdown files, so one can be
    written in any editor and passed around — and a prompt file supplies wording
    only: it cannot add tools or steps, and a file that asks is imported as text
    with the request named.
  • Tools, gated by you. Local actions through AppFunctions Jetpack and
    external servers through the Model Context Protocol (MCP), with reusable
    skills (instruction + tool allowlist + context) as pipeline steps. Every
    sensitive or destructive call stops for explicit confirmation — the allowlist
    is enforced at the executor level, not merely suggested.
  • Reaches you from outside the app. A share target, launcher shortcuts, and
    a Quick Settings tile run your chosen pipeline over shared text/images or in
    the background. Triggers (time, charging, Wi-Fi, network) fire a pipeline
    on their own and report back with a notification. Every entry surface stays
    inert until you bind a pipeline to it — a privacy-first default.
  • Complements your automation app. Tasker, MacroDroid or a shell script over
    adb can ask the agent to run one pipeline you nominate: they decide when,
    the agent does the language-model part of what. Off by default and behind an
    explicit consent dialog; the binding is an allowlist, not a fallback, so a
    request naming anything else is refused rather than redirected. Every inbound
    request — accepted or refused — lands in a readable journal.
  • Local-first by construction. The Room database is SQLCipher-encrypted and
    API keys are sealed with AES-GCM under a dedicated Android Keystore key.
    On-device usage statistics (a build-time guard forbids any network on that
    path), attachment images that never reach cloud models, and voice input
    transcribed on-device before the pipeline runs. A FOSS build ships with
    zero proprietary dependencies for F-Droid.
  • Reliable over long, autonomous runs. A validate-and-repair gate keeps
    structured nodes producing well-formed output, exponential-backoff retry
    smooths transient cloud failures, and background history compression keeps a
    long session from overflowing the context window. Interrupted runs resume from
    their last completed node; reopening a chat reconnects to a run still
    executing in the background. A run nobody is watching is bounded by step and
    token ceilings counted across the whole run tree — so an automation that
    starts looping cannot quietly spend your cloud key — and a run stopped that
    way says so instead of looking broken.
  • Remembers what matters. Long-term memory with semantic retrieval (RAG)
    over past conversations, automatic fact extraction, manual "Save to memory,"
    and a memory manager with search, provenance, compaction, and JSON
    export / import.
  • A chat list that stays a working list. Archive a conversation to take it
    out of the drawer without deleting a single message: it waits, whole and
    exportable, on its own screen until you restore it — and opens read-only in
    the meantime, so nothing brings it back except you.

The full feature tour lives in the user guide.

Screenshots

The pipeline editor below is a capture from a phone running the app. The other
three are rendered at 1080 × 2400 from a Roborazzi baseline
(./gradlew :catalog:recordRoborazziDebug --tests "*HeroSnapshotTest*"), which
keeps them and the design-system regression suite in sync — the editor canvas is
an app screen rather than a design-system component, so it has no baseline to
render from. Hover over (or tap) an image to see the dark variant via your
browser's prefers-color-scheme.

Pipeline editor on a phone: a 22-node pipeline on the canvas, with routers, nested sub-pipelines, queues and tool steps wired together
Pipeline editor — a 22-node pipeline on the canvas: routers, nested sub-pipelines, queues, tools, on-device and cloud steps
Pipeline library — saved pipelines
Pipeline library — saved pipelines + import-from-browser-editor JSON
Tools — built-in AppFunctions and expanded MCP server
Tools — built-in AppFunctions + MCP servers with per-tool risk + toggle
Settings — searchable hub with Basic controls and eight categories
Settings — searchable hub with inline Basic controls over eight category sub-screens

Requirements

  • Android 14 or newer (API level 34+). A few OS-integration features need
    Android 16: calling functions that other apps expose, and the strict
    intent-matching rules that harden the external-automation entry point. On
    Android 14 and 15 everything else — local models, cloud providers, MCP
    servers, triggers, scheduled tasks — works unchanged.
  • Approximately 2 GB of free RAM available for the LLM at runtime.
  • Optional: hardware acceleration via NPU or GPU for noticeably faster
    inference. CPU-only operation works but is slower.
  • Optional: location permission, requested only if you scope a Wi-Fi
    trigger to specific network names (Android ties the Wi-Fi name to location).
    Nothing else uses it, and the name never leaves the device.
  • To build from source: JDK 21 and the Android SDK (the Android Studio
    bundled JBR already ships JDK 21). See CONTRIBUTING.md for
    the full dev setup.

Install

From Google Play

Knotwork on Google Play
— the simplest route, and the one that updates itself. Requires Android 14+.

The Play build is the full flavour described below. It shares a signing key
with the APKs on the Releases page, so you can move between those two channels
without reinstalling.

From a release build

Grab the latest APK from the
Releases page and install it
on an Android 14+ device. Two flavours are published:

  • full — the standard build, with opt-in Firebase Crashlytics for
    anonymous crash reporting (off by default, never collects message content).
  • foss — zero proprietary dependencies and no crash reporting, suitable
    for F-Droid. See docs/release.md § FOSS / F-Droid build.

Upgrading from 0.6.0 or earlier requires a clean install. Those builds
were signed with the Android debug keystore; 0.7.0 is the first release
signed with a real release key. Android refuses to update an install whose
signer changed, so you must uninstall the old build — which clears its local
data — before installing 0.7.0. Export anything you want to keep first.
This is a one-time break; later releases update in place. See the full
pre-release notice below.

Build from source

git clone https://github.com/alexeyw/knotwork.git
cd knotwork
./gradlew assembleFullDebug
adb install app/build/outputs/apk/full/debug/app-full-debug.apk

First run

Launch the app and let scenario onboarding guide you: pick a scenario and
Knotwork sets up its pipeline and downloads exactly the model it needs, then
opens into a working chat once the model has warmed. Prefer to wire things up
yourself? Choose Start from scratch, then open Models, download a
LiteRT model through the built-in manager (or paste a custom URL), and send your
first message once it loads.

Tech stack

Layer Technology
Language Kotlin
UI Jetpack Compose + Material Design 3
Design system Knotwork (in-tree :catalog library)
Brand fonts Inter + JetBrains Mono (bundled TTF, SIL OFL 1.1)
LLM engine LiteRT-LM (Google Edge AI / ex-TensorFlow Lite)
Tool calling AppFunctions Jetpack
MCP & cloud LLM Koog (MCP transport + cloud-LLM client only)
Architecture Clean Architecture + MVVM
DI Hilt
Async Coroutines / Flow
Serialization kotlinx.serialization (structured-output validation)
Network OkHttp + Ktor (via Koog)
Image loading Coil 3 (attachment thumbnails / viewer)
Local storage Room + DataStore
Crash reporting Firebase Crashlytics (full flavour) / none (foss)
Distribution full (Play / direct APK) + foss (F-Droid, no Google)
Testing JUnit + MockK; instrumented suite on an emulator matrix in CI
Architecture tests Konsist (Clean-Architecture layer guard, in check)

Privacy

Knotwork has no account, no sign-in, and no server of its own. There is nothing
to log into, and nothing is uploaded for the app to work.

  • Conversations stay on the device by default. Inference runs locally
    through LiteRT-LM. Data leaves the phone only through a path you configured
    yourself: a cloud LLM node with your own API key, or an MCP server you added.
    Both are opt-in and both are visible in the pipeline you built.
  • Usage statistics are local-only. The in-app statistics are computed and
    stored on the device and are never transmitted; a build-time architecture
    guard fails the build if any network dependency reaches that code. Exporting
    them is a manual action you take.
  • Crash reporting is opt-in and off by default. In the full flavour you
    can enable anonymous crash reports (stack traces, device model, Android and
    app version, the active pipeline and model identifiers). Message content,
    prompts, memory, and API keys are never included. The foss flavour has no
    crash-reporting dependency at all and hides the setting.
  • Sensitive data is encrypted at rest. The local database — chats, long-term
    memory, run traces — is SQLCipher-encrypted, and API keys, the Hugging Face
    token, and MCP credentials are sealed with AES-GCM under a dedicated Android
    Keystore key.
  • The agent asks before it acts. Destructive and sensitive tool calls stop
    at a human-in-the-loop confirmation, including when a pipeline runs in the
    background from a trigger.

The policy in full — what is stored on the device, every path that can send
data off it, and how to switch each one off — is PRIVACY.md. The
threat model behind it, including what is explicitly out of scope, is in
SECURITY.md; the per-feature behaviour is in the
user guide.

Documentation

Pre-release notice

This project is currently at version 0.8.0 and is published for review and
experimentation. Expect rough edges:

  • There are no stability guarantees for the public surface (Kotlin APIs,
    pipeline JSON schema, settings layout) between versions.
  • On-device storage formats (encrypted preferences, exported pipeline JSON)
    may still change between versions.
  • Shared pipeline files are not yet a compatibility contract. Exported
    pipelines and bundles carry a version stamp (schemaVersion: 1,
    bundleVersion: 1), but before 1.0 that stamp is a marker, not a promise:
    the schema may change without a major bump, and no import-time migration is
    provided. A file whose stamp does not match the build importing it is not
    rejected — it is imported on a best-effort basis behind an explicit
    warning. What the import does now tell you is exactly which settings it
    could not read, by name, whether or not the stamp matches — because the
    format adds fields without bumping the stamp, so a matching version is no
    guarantee that nothing was lost. Keep the original file anyway: naming the
    loss is not the same as preventing it. At 1.0 at
    the latest the format becomes a semantic-versioning contract: a breaking
    change then means a major schemaVersion plus a migration applied on import.
  • Upgrades preserve local data. Every Room schema-version bump ships with
    an explicit migration, so an in-place update keeps your chat history,
    long-term memory, run traces, custom pipelines, and saved presets / prompt
    templates. (Note: downgrading to an older build recreates the database
    empty — forward migrations cannot be reversed — so export anything you want
    to keep before installing an older version.)
  • The signing identity changed at 0.7.0 — a one-time upgrade break.
    Builds up to and including 0.6.0 were signed with the Android debug
    keystore; 0.7.0 is the first release signed with a real release key.
    Android refuses to update an install in place when the signer changes
    (signature mismatch), so upgrading from 0.6.0 or earlier means uninstalling
    the old build first — which clears its local data. Export anything you want
    to keep before you do. Releases from 0.7.0 onward share one signer and
    update in place normally.

License

Released under the Apache License 2.0. See LICENSE for the full
text.

Reviews (0)

No results found