halkyon/apps/learn/halkyon_learn_agent/README.md
Tizian 「ティツィアーン」 54e212a51c
Some checks failed
CI / check (push) Failing after 1m56s
feat(learn): Learn's agent, an MCP server suggesting in shared studysets
Halkyon's ADR 0044, step 6c (D7, D49 to D52). apps/learn/halkyon_learn_agent
is one executable, `halkyon-agent --instance URL sign-in | sync | mcp`:

- sign-in keeps the token read from stdin, signs in with it, makes the
  agent's key pair on its first sign-in, keeps it before setting the
  public halves on the register (agents.setKeys), and syncs;
- it opens its data as the app's _openPersonData does, on
  halkyon_learn_core and halkyon_content: its own SQLite database, the
  sync's space router, its keys and those of the spaces shared with it,
  and the repositories of studysets, cards, notes, paths, files and
  feedback;
- mcp serves ten tools over stdio (dart_mcp): list, read and search the
  studysets shared with it, suggest a change or a new card or note,
  report, list a studyset's suggestions and reply. Each syncs first and
  a suggestion again at once; a refusal is the tool's error;
- its files live in $XDG_CONFIG_HOME/halkyon-agent/<host>, 0700 and
  0600, refused when others may read them (D50);
- tool/install.sh builds it with `dart build cli` (libsodium and SQLite
  bundled) and copies it to its user on the host, the build before kept
  (D52).

The synced gateways of learning paths and files, and the fakes of the
core's gateways, move into halkyon_learn_core (its testing.dart), which
the app's tests and the agent's share.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-11 22:08:31 +01:00

3.2 KiB

halkyon_learn_agent

Halkyon Learn's agent (Halkyon's ADR 0044, D6, D7, D10, D49 to D52): an account of its own on an instance, made in a person's Profile (Agents) and invited as a Viewer to the studysets they share with it. It reads their cards and notes and suggests: changes, new cards and notes, reports of what should go, replies. It never writes into a studyset; its Owner and Editors accept or decline in the app (a studyset's Suggestions). Claude Code, or another MCP client, reaches it over stdio.

Using it

On the machine it runs on, as a user of its own (D7; halkyon.li's host at home):

  1. Build and copy it there from a laptop with Dart, tool/install.sh <ssh target> (D52). It builds for the laptop's architecture (dart build cli, libsodium and SQLite bundled; the host needs no Dart) into ~/.local/lib/halkyon-agent/<commit>, ~/.local/bin/halkyon-agent pointing to it, the build before kept.

  2. Sign in once with the token its owner copied from their Profile, on stdin, never as an argument others on the machine could see:

    $ halkyon-agent --instance https://halkyon.li sign-in < token.txt
    

    It keeps the token, makes its key pair and sets the public halves on the register, syncs and says how many studysets are shared with it.

  3. Let Claude Code start it:

    $ claude mcp add halkyon -- ~/.local/bin/halkyon-agent --instance https://halkyon.li mcp
    

halkyon-agent --instance … sync syncs once, e.g. to see that it still can.

Its tools

list_studysets, read_studyset (title, description, topics, cards and notes as plain text), search_cards, suggest_card_change, suggest_new_card (front and back, or a vocabulary card's word, reading and meanings), suggest_note_change, suggest_new_note, report, list_suggestions (with replies and what was decided) and reply. Only studysets shared with it count. Each call syncs first and a suggestion syncs again at once; a sync that fails leaves what it holds to read, and the result says so. A refusal (a studyset not shared with it, a card it can't find) is the tool's error, which the model reads.

What it keeps

$XDG_CONFIG_HOME/halkyon-agent/<host>[_<port>]/ (else ~/.config/…), the folder 0700 and its files 0600, refused when others may read or change them (D50): token, keys.json (its key pair, unsealed: its user's boundary protects it), keys_set, sync.sqlite (the shared studysets, opened as the app opens them), key_pins.json (the members' public keys as first seen), privacy.json and files/. An instance is reached over HTTPS, or plain HTTP on the same machine alone. Its session is kept in memory, a sign-in with the token at every start.

Code

  • lib/src/open_agent.dart signs in and opens its data as the app's _openPersonData does, on halkyon_learn_core (its gateways and repositories) and halkyon_content (keys, shared spaces, files).
  • lib/src/agent_library.dart reads and suggests, lib/src/agent_server.dart makes tools of it (dart_mcp), lib/src/agent_sync.dart syncs on demand, lib/src/agent_home.dart keeps its files; bin/halkyon_agent.dart is the CLI. Tests run on the core's fakes, without a server.

Licensed under the AGPL-3.0.