Skip to content

Latest commit

 

History

History
485 lines (432 loc) · 34.2 KB

LP-0008.md

File metadata and controls

485 lines (432 loc) · 34.2 KB

Solution: LP-0008 - Autonomous AI Agent Module

Submitted by: aegonmyy

Summary

A Logos-native autonomous agent, packaged as a Logos Core module, with native access to the full stack: a shielded LEZ wallet, Logos Storage, and Logos Messaging. The agent has its own shielded identity and funds, acts autonomously within an owner-set spending threshold, escalates over-limit spends to its owner over an end-to-end encrypted channel, and coordinates with peer agents through an A2A-compatible protocol that settles payment in LEZ. It is deployed headless with a single command and driven from a Basecamp owner mini-app. Every default skill is implemented behind a documented, third-party-extensible skill interface.

The agent's on-chain activity is proven on the official public LEZ testnet with real Groth16 proofs (RISC0_DEV_MODE=0), and the full multi-agent and multi-use-case flows are demonstrated end-to-end against a real local sequencer.

Repository

MIT OR Apache-2.0 licensed. CI is green on the default branch (a clean-room build plus an end-to-end integration job against a standalone LEZ sequencer); the pinned green run is 34326620286 (commit 22e9cee, 2026-09-09). Every verification path below is either a live link you can open, a command you can run, or a test you can execute; on-chain claims were re-verified against the public RPC on 2026-09-09.

Approach

Runtime and skills. The agent core is a Rust crate exposing a Skill trait (one async method) and a SkillRegistry that dispatches by name. New skills are added by implementing the trait and registering - no core changes - which satisfies the "third parties can add skills" requirement. meta.skills lists the catalogue for discovery. The core is exported both as a normal Rust library and as a C-ABI cdylib that the Logos Core module loads.

Logos Core module + Basecamp app. The agent ships as a Qt Remote Objects plugin (module/) loaded by logoscore alongside wallet/storage/messaging, plus a ui_qml Basecamp owner app (app/) that talks to it over RemoteObjects. Both build with the Logos module builder; scripts/package-basecamp.sh produces standalone, side-loadable .lgx bundles. The module dlopens the Rust core built by scripts/build-ffi.sh (pinned to the runtime's nixpkgs so glibc/libstdc++/ libpython match); loading and executing a skill end-to-end inside logoscore is recorded in docs/LOGOS_CORE_LOADED.md.

Identity, spending, owner channel. The agent holds its own LEZ account and transacts independently of the owner. A per-transaction limit is enforced in the Agent type: below it, transfers execute autonomously as privacy-preserving transactions; above it, the agent posts an approval request to the owner over two derived Logos Messaging topics and waits. The over-limit path notifies the owner first and only then holds the spend - a notification that cannot be delivered is retried and the spend is never held or executed. Pending approvals persist to disk and are restored on restart, so a node/network interruption does not drop them.

A2A coordination. Agent Cards follow the A2A schema; task interactions follow the A2A lifecycle (submitted → working → completed/failed/canceled). The two things A2A leaves open - transport and payment - are filled by Logos Messaging (replacing HTTP) and a real LEZ token transfer per task. Cancellation triggers a real refund. This is documented as an A2A transport binding over Logos Messaging.

Why the Logos stack. The agent is sovereign: it owns its keys, holds and spends its own funds, stores encrypted data, and communicates over infrastructure no single party controls. LEZ gives it a shielded account indistinguishable on-chain and trustless per-task micropayment; Logos Messaging gives it an end-to-end encrypted owner channel and A2A transport with no central server; Logos Storage gives it client-side-encrypted persistence. A centralised alternative would reintroduce a custodian for funds, a server for messaging, and a data host - exactly the dependencies this design removes.

What was hard. The public testnet advanced from LEZ v0.2.0 to v0.2.4 mid-development. A v0.2.0 client could sync the v0.2.4 chain but its transactions were accepted into the mempool and never included - the write path changed across v0.2.1's L1-fees and the private-kinds refactor. Matching the client to v0.2.4 made the identical transaction include; see docs/TESTNET_EVIDENCE.md.

Success Criteria Checklist

  • Loads in Logos Core alongside wallet/storage/messaging without modifying them - the agent ships as a Qt plugin in its own module directory, added to the stock runtime through the standard extra-module path (-m <agent-install>/modules); the stock logoscore binaries and their wallet/storage/messaging modules are used exactly as built, with nothing recompiled, patched, or replaced on their side. The runtime loads the module and invokes it end to end:
logoscore --config-dir "$LC" load-module agent
logoscore --config-dir "$LC" call agent invokeSkillJson storage.upload '{"label":"vault","data":"secret via logos core"}'

Full transcript and setup: docs/LOGOS_CORE_LOADED.md.

  • Own shielded LEZ account, sends/receives independently of the owner (tests/agent_spending.rs, tests/three_category_agents.rs). Proof-bearing activity on the public testnet, every row re-verified against the public RPC on 2026-09-09: the agent's shielded mint and three shielded spends, all PrivacyPreserving (type 0x01; a Public transaction is a few hundred bytes, so an on-chain body of ~270 KB means the Groth16 proof is in it):
Transaction Block Body
a178944818bc67ee776bcc9ca4e8bf5a798b4d1cf1aab8ce5a84650c079799c6 (mint) 87 270,810 B
a3eaeb3a773f35a48935944ca1b15bed683265dbded90633c094e4ef56aa4f4b (spend) 88 272,778 B
2a283d3c8887ef552bf56f415bbd6b534a4424e0765b590f3b44f6f6215a0aaa (spend) 111 273,066 B
eab567f88e164945769c342d35540c7e7ae610c267c4247d877868ae51af8b93 (spend) 118 270,480 B

The block explorer renders these rows as well and independently reports the proof size (261,095 B proof inside the 270,810 B mint body); the raw RPC returns the exact bytes, which is what the counts below are measured with:

curl -s -X POST https://testnet.lez.logos.co -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"getTransaction","params":["a178944818bc67ee776bcc9ca4e8bf5a798b4d1cf1aab8ce5a84650c079799c6"]}' \
  | jq -r '.result[0]' | base64 -d | wc -c
# -> 270810

Committed RPC snapshots of all four: docs/testnet-evidence/v0.2.0/rpc/ (mint-01.json, spend-01..03.json).

Each category agent also lands its own included, state-changing settlement through a program the agents deployed on the public testnet (tests/three_testnet_settlements.rs): deployment tx 810ac460c5bb2b46a3868fb699635be5059496478db48c98809c107a04ee3d67 (block 144, a 343,397-byte ProgramDeployment), then three Public settlements (explorer-clickable; by design proof-free, the proof evidence is the shielded set above):

Category Transaction Block
storage 155731c6...f74416cf 148
messaging adf2ae74...04f94d9c 149
blockchain f589abe4...be15bd54 150

State re-verified via RPC: each claimed account's program_owner decodes to exactly the deterministic program id 937554f71c96d8ace11298d2d3342e0b4ffa7d61fb394c1706a78c088f4ea471, nonce 1:

curl -s -X POST https://testnet.lez.logos.co -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"getAccount","params":["Eh3VZWvqR7ykNhbGUCpJASVFMZKK1uSP6Coooon691LB"]}'
# -> program_owner = [4149507475, 2899875356, 3533181665, 187577555, 1635646031,
#    390871547, 143435526, 1906593423]  (= the program id in u32 words), nonce 1

Category-agent token mints on the public testnet, live-verified: storage 9b510890642f95a10ac4b75ffa6a121c262c065343c44906297347f5ef4266ce (block 458, 270,845 B) and messaging 328d26a709447c40805fa64eba407a2aa2d91473068434351617a519cb62732e (block 317, 270,855 B) and blockchain 5fc57a20966a637f860e3139dbd2003f9f35ba556d7974156cffc291e3cb560b (block 338, 270,860 B). Node serving of older heights is intermittent - block 338 read null during the 2026-09-09 morning re-verification and was serving again hours later - so the durable record is the committed RPC snapshots (docs/testnet-evidence/v0.2.0/rpc/); every hash in this file was live at the 2026-09-09 re-verification, and the reproducible tests regenerate equivalent evidence against whatever chain is live. Full maps: docs/TESTNET_EVIDENCE.md, docs/THREE_TESTNET_SETTLEMENTS.md, docs/THREE_TESTNET_AGENTS.md, docs/SHIELDED_TESTNET_PROOF.md.

  • Single-command headless deploy - the agent binary (src/bin/agent.rs); deploy + configure is one command:

    agent --owner demo-owner --spending-limit 50 --period-limit 500 \
          --period-seconds 86400 --messaging-url http://127.0.0.1:8645 \
          --state-file /tmp/agent-demo/agent-state.json

    Every flag also reads from an environment variable (AGENT_OWNER, AGENT_SPENDING_LIMIT, AGENT_PERIOD_LIMIT, AGENT_PERIOD_SECONDS, AGENT_MESSAGING_URL, AGENT_STATE_FILE). The once-per-machine wallet home is created by agent-wallet-init --sequencer https://testnet.lez.logos.co; a recorded run of both steps against the public testnet, including the recovery-phrase output, is docs/HEADLESS_DEPLOY.md.

  • Owner interacts from a separate Logos app over Logos Messaging, no intermediary server - the Basecamp bundle builds with the Logos module builder. The owner-channel Rust FFI (src/ffi.rs, logos_agent_owner_*) is implemented, unit-tested, and verified across the C ABI, and the QML approve/deny UI is written. Two runtime runs drive a live agent through the FFI owner handle (the exact boundary the Basecamp app calls): tests/owner_ffi_e2e.rs (non-ignored; runs in CI) does hold → FFI poll → FFI approve → on-chain execution (balance 100→50), FFI deny (no movement), FFI reconfigure → autonomous spend on the real local sequencer; and tests/owner_ffi_waku.rs runs the same hold → poll → approve → execute flow with real Waku as the transport - the agent and the FFI owner handle each run their own client against a live nwaku node (Logos Dev Network, cluster 2) and never share memory, the approved spend still executing on-chain (balance 100→50). The FFI + Waku messaging path the Basecamp app calls is proven end to end, and the running app itself is recorded: the Basecamp GUI demo (https://youtu.be/1Ck_0keFXek) shows the owner app polling, approving, denying, and reconfiguring a live agent over real Waku, with every decision settled on-chain (see the video criterion below).

  • Spending threshold holds above-limit spends for approval and executes below-limit ones autonomously, gated by both the per-transaction and the per-period limit (tests/owner_approval_flow.rs: the per-tx flow and a dedicated per-period flow that holds a period-over spend, releases it on approval, holds a second spend against the same accumulator, and denies). A shared Agent::check_policy backs both the skill path and the owner-approval path so the two enforce the same policy.

  • All default skills implemented and documented - Storage (4), Messaging (3), Blockchain (wallet.balance/send/history, program.query/call/deploy), the five A2A agent.* skills, Meta (meta.skills/status/configure).

  • A2A-compatible Agent Cards + task lifecycle, documented as a transport binding over Logos Messaging (src/a2a.rs, README). Each card is Ed25519-signed by its publisher and embeds its verifying key, so tampered cards fail AgentCard::verify (src/a2a.rs).

  • Two agents discover, run a task, and settle LEZ payment autonomously against the standalone sequencer with real proofs (tests/a2a_two_agents.rs, docs/THREE_USE_CASES.md).

  • Real testnet activity and three use cases - the three use cases (personal file vault, privacy-preserving notary, paid multi-agent task) run reproducibly against a real local LEZ sequencer in tests/three_use_cases_local.rs (non-ignored; runs in CI and scripts/demo.sh; the test brings up its own Docker sequencer):

cargo test --test three_use_cases_local -- --nocapture
# or the full real-proof run: RISC0_DEV_MODE=0 ./scripts/demo.sh

Vault and notary round-trip over storage + messaging, and the paid task settles a real on-chain LEZ transfer (payment tx 3d065660d4f7d97ddaae0f4f78bff0d59f5995c32377ad0dfa35c5e199456c96, block 17 of the run's sequencer, balances 90/10; the full 58-minute RISC0_DEV_MODE=0 capture is committed at recordings/vault-notary-real-proof.cast). The vault, notary, and event-alerter use cases are additionally anchored on the public LEZ testnet with real Codex storage and real Waku messaging in the loop (tests/three_use_cases.rs), all three anchors re-verified against the public RPC on 2026-09-09:

Anchor Transaction Block
vault (real Codex CID zDvZRwzm4zQmJH7UbbL7MAUJDhhmy2ZwqaT7nGgedzJxhfCyXS7y) 54bfd294619753f13edcfd136694e7530e6afe9b2d7130f26e677b29e87fb35d 747
notary (document digest 5999d285f64e95b7d4f1246a112d45535e852676d06f14530900876f4638a42a) 5a90dd7740cecec6a6bd35738d02d913426796bd5cd1acdb5741fdbf8bc9f966 748
alerter c9d8debda7f930354d3d1f1e764a3880277581123aa68056383d11933a0c2200 749
curl -s -X POST https://testnet.lez.logos.co -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"getTransaction","params":["54bfd294619753f13edcfd136694e7530e6afe9b2d7130f26e677b29e87fb35d"]}'
# -> a 373-byte anchor transaction (rows 748/749: 377/381 bytes)

Earlier same-epoch anchors (blocks 402-404 memory backends, 405 + 407 real services, 633) have aged out of the node's serving window and now read null; the live-verified public-testnet set is the rows above plus the category mints under the three-agents criterion. The shielded-transfer leg is evidenced on the local standalone sequencer with real proofs (payment tx above, balances 90/10) and on the public testnet by the agent's shielded spends listed under the account criterion (blocks 88, 111, 118, live-verified) and re-landed on demand by tests/testnet_shielded_probe.rs, a required step of the real-proof-e2e workflow whose green run on 2026-09-09 landed a fresh 271,076-byte shielded send (tx 6c5aa75e..., block 1225). The public-testnet settlement leg is the program-mediated settlements under the account criterion (blocks 148-150, explorer-clickable). Full story: docs/THREE_USE_CASES.md, docs/TESTNET_EVIDENCE.md, docs/SHIELDED_TESTNET_PROOF.md (which also records the transient 2026-08-22 dropped-private-transaction condition, no longer reproducible).

  • Documented, third-party-extensible skill interface (Skill trait + SkillRegistry), specified per skill in docs/SKILL_INTERFACE.md (all 21 default skills) and proven from outside the crate by tests/third_party_skill.rs (an out-of-tree crate registers a skill, dispatches it, is listed by meta.skills, and shadows a default), run in CI:
cargo test --test third_party_skill -- --nocapture
  • Reliability, each clause pinned to a named test you can run: pending-approval state persists across restarts (held_spend_survives_restart_and_executes_after_approval in tests/owner_approval_flow.rs: the process is killed mid-hold, the owner approves while it is down, and the relaunch executes the spend on chain), the per-period spending accumulator is persisted so restarts cannot reset the period allowance (same test file), an undeliverable owner notification is retried before the spend is dropped (transient_owner_outage_is_retried_and_the_spend_holds pins fail-once-retry-deliver; unreachable_owner_means_no_pending_spend pins total failure), and skill failures are isolated (failing_skill_is_isolated_and_does_not_affect_other_tasks in src/a2a.rs: a deliberately failing skill and a working skill are served in the same round; the failing task surfaces as failed with its error and the neighbouring task completes normally):
cargo test --test owner_approval_flow -- --nocapture
cargo test --lib transient_owner_outage_is_retried_and_the_spend_holds -- --nocapture
cargo test --lib unreachable_owner_means_no_pending_spend -- --nocapture
cargo test --lib failing_skill_is_isolated -- --nocapture
  • CU costs documented per operation from measurement (docs/CU_COSTS.md).
  • E2E tests against a standalone sequencer, in CI, and CI green on the default branch. Two workflows, by design. The fast lane (ci.yml, every push) runs a clean-room build, unit tests, and an e2e job (agent_spending, owner_approval_flow, owner_ffi_e2e, a2a_two_agents, three_use_cases_local, three_category_agents) against a Docker local sequencer at RISC0_DEV_MODE=1; pinned green run 34326620286 (commit 22e9cee, 2026-09-09, self-hosted Linux runner; every job in it is clickable per test). The real-proof lane (real-proof.yml, dispatched on demand on the exact commit under review so a push can never cancel a proving run) runs RISC0_DEV_MODE=0 throughout with both steps required and no continue-on-error anywhere in the file; pinned green run 34326632248 on the same commit 22e9cee: the agent spending flow against a local sequencer (86 minutes of real Groth16 proving) and the public-testnet shielded-send probe, which landed a fresh proof-bearing transaction from CI, tx 6c5aa75e369088f48839321c26fe6d7ff49e3a150fa3edc256ce4bdd4649ce70, block 1225, 271,076 bytes, type byte 0x01, included 8 seconds after submission (mint block 1193, holder balance 100 -> 90); verify it live with the getTransaction curl pattern above. On proof validity: CI generates real proofs at DEV_MODE=0 (that is what the 86 minutes is) and asserts the landed body's type and size; the operator-run public chain performs the cryptographic verification at inclusion, and the block explorer independently reports the proof size for this transaction class (261,095 B inside the 270,810 B mint body). The durable evidence is what the chain itself carries today: the shielded mint and spends of blocks 87-118 under the account criterion (270-273 KB proof-bearing bodies, RPC-verified above), the committed snapshots of all four at docs/testnet-evidence/v0.2.0/rpc/, and the CI-landed block-1225 transaction above. The RISC0_DEV_MODE=0 path is additionally evidenced by the reproducible demo.sh (below) and the public-testnet settlements of blocks 148-150 (run at DEV_MODE=0, verified in 170.5 s). The pinned runs sit on 22e9cee; this file's own commit changes only documentation and comments relative to that commit. See docs/SHIELDED_TESTNET_PROOF.md.
  • Reproducible demo.sh against a real local sequencer at RISC0_DEV_MODE=0; full docs (architecture, skill interface, spending controls, A2A, security model, deployment + owner-interaction guide).
  • Narrated video demo showing terminal output including proof generation (RISC0_DEV_MODE=0), the Basecamp app GUI, and the CLI, narrated by the builder. Three narrated videos cover the criterion:
  1. Terminal + real-proof + CLI (https://youtu.be/HS6i3ucrKeE?si=hsgTfdJ7YSS0rnNK, ~13 min): the builder narrates the real-proof terminal output across the three scenarios (sovereign wallet, owner control, agent marketplace) against a local LEZ sequencer at RISC0_DEV_MODE=0, calling out real Groth16 proof generation as it happens. Raw recording and retiming script: recordings/logos-agent-real-proof.cast, recordings/retime_cast.py.
  2. Three use cases, the builder's own voice (https://youtu.be/dg6RuNw44a8): a narrated walkthrough of the prize's illustrative use cases - what each use case is, what the agent actually does at each step (encrypt and store the vault file, record and verify the notary digest, discover and pay for a task), and the architecture behind it - cut from the 58-minute RISC0_DEV_MODE=0 capture of the single test run that executes all three (recordings/vault-notary-real-proof.cast).
  3. Basecamp GUI demo (https://youtu.be/1Ck_0keFXek, 4 min 32 s, 1920x1080): the builder narrates a human-driven recording of the Basecamp owner app driving a live autonomous agent through the full owner-approval lifecycle over real Waku messaging, with every decision settled on a real local LEZ sequencer. A real human drives the GUI over VNC with a real cursor; subtitles are available via YouTube CC. Four stages: approve an over-limit spend (100 -> 50), deny a spend (no movement), reconfigure the per-tx limit (30 -> 45), and an autonomous spend under the raised limit (50 -> 10), the last surfaced to the owner via a "spent" notice the app polls. See docs/BASECAMP_GUI_DEMO.md; reproduce with scripts/record-gui-demo-interactive.sh (human-driven) or scripts/record-gui-demo.sh (headless). Together the three videos cover the terminal output with real proof generation, the Basecamp app GUI, and the CLI. Reviewer tip: turn on YouTube subtitles (CC); all three videos are narrated and carry subtitles.

FURPS Self-Assessment

Functionality

A shielded identity with policy-gated spending; the full default skill set across Storage, Messaging, Blockchain, and Meta; an owner-approval workflow; and A2A coordination that discovers peers and settles LEZ payment per task autonomously, with real refunds on cancel. Packaged as a Logos Core module paired with a Basecamp owner app. Limitation: no AI model is bundled - the skill interface is model-agnostic and inference is left to the deployer (out of scope per the prize; docs/limitations.md).

Usability

Skills are added by implementing one trait and registering - no core changes. Deployment is a single command; all flags also read from environment variables. The owner acts both over the encrypted channel (programmatically) and through the Basecamp owner app, whose assets are provided as source and as side-loadable .lgx bundles, attached as release assets (agent.lgx, agent_owner.lgx, and the runtime-matched liblogos_agent.so with checksums) at https://github.com/aegonmyy/logos-agent/releases/tag/v0.2.0-basecamp-bundles (built from source commit 2c2bfcd; the changes from 2c2bfcd to the pinned implementation commit touch no build input, only documentation, workflow comments, and a test doc-comment).

Reliability

Unapproved over-limit spends never execute; an owner notification that cannot be delivered is retried before the spend is dropped. Pending approvals and A2A task state persist to disk and are restored on restart. Skill failures are isolated and surfaced rather than fatal.

Performance

On-chain operation costs are measured, not estimated, with the platform's cycle_bench tool (docs/CU_COSTS.md):

Operation Program · instruction User-cycles (CU)
Pay for a task / wallet.send token · Transfer 127,726
Fund an account (token issuance) token · Mint 116,862
Burn tokens token · Burn 116,546
Native authorized transfer authenticated_transfer · Transfer 79,958
Account initialization authenticated_transfer · Initialize 43,818
Create associated token account associated_token_account · Create 174,995

The public-execution budget is 33,554,432 cycles (32M), so a token Transfer at ~128k cycles uses ~0.4% of the budget. Real-proof generation for a private transaction is on the order of minutes on commodity hardware.

Supportability

End-to-end integration tests run against a real local sequencer and are wired into CI as a dedicated e2e job; CI is green on the default branch. A reproducible demo.sh runs the curated scenarios at RISC0_DEV_MODE=0. The codebase is small and modular (one file per concern: skills, a2a, owner, storage, messaging, ffi), with a documented skill SDK for future maintenance.

Supporting Materials

Terms & Conditions

By submitting this solution, I confirm that I have read and agree to the Terms & Conditions.