Skip to content

feat: intent-routing example + approve_federation_agent command#369

Merged
toadkicker merged 15 commits intomainfrom
feat/0a75-examples
Apr 24, 2026
Merged

feat: intent-routing example + approve_federation_agent command#369
toadkicker merged 15 commits intomainfrom
feat/0a75-examples

Conversation

@toadkicker
Copy link
Copy Markdown
Contributor

Summary

  • examples/intent-routing: New self-contained example demonstrating Papillon's real 2-level intent pipeline — URL fast-path (detect_intent) → BM25 semantic index (IntentIndex::classify) → honest DuckDuckGo fallback. Comments explicitly explain that BM25 is a term-frequency scorer and the prompts are cherry-picked catalog matches. The resolved action type drives a full 6-phase PAP handshake (mandate → delegation → session → co-signed receipt).
  • DynamicAgentSource::Federation: New enum variant marking agents approved from federation peer registries. No local keypair (operator_key_seed = None) — the operator's DID is the signing authority. Fixes the non-exhaustive match in papillon-shared/src/db/native.rs.
  • approve_federation_agent Tauri command: validates advertisement signature via verify_key_from_did + ad.verify(), converts to a DynamicAgentDef with source = Federation, persists to SQLite, and registers in the live local registry. Federation agents are immediately visible to IntentIndex (BM25) on the next IntentIndex::new() call — closing the gap where AgentAdvertisement objects from remote registries were invisible to the BM25 routing layer.

Test Plan

  • cargo test -p pap-intent-routing — 6 tests pass (BM25 routing, URL fast-path, fallback, full handshake integration)
  • cargo test -p pap-agentsdynamic_agent_source_variants_round_trip + federation_source_serializes_as_federation pass
  • cargo test -p papillon --lib commands::agents — 7 tests pass including approved_federation_def_is_visible_to_bm25
  • cargo test -p papillon -p papillon-shared -p pap-agents -p pap-intent-routing — 353 tests, 0 failures
  • cargo check -p papillon — clean compile after rebase on main

🤖 Generated with Claude Code

Todd Baur and others added 13 commits April 24, 2026 10:55
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
… fallback

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
… handshake

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
BM25 scores on term overlap — prompts with no shared tokens score zero
and fall through. Added comment explaining this so readers don't think
the index magically handles all prompts.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Covers DynamicAgentSource::Federation variant, ad_to_federation_def
helper, approve_federation_agent Tauri command, and BM25 integration
test proving approved agents are routable after promotion to local DB.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Marks agents approved from federation peer registries. No local keypair
(operator_key_seed is None) — the operator's DID is the signing authority.
Adds serde round-trip test for the new variant.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Wire DynamicAgentSource::Federation into source_to_str() and the
  papillon-shared DB insert match
- Add ad_to_federation_def() helper: converts a verified AgentAdvertisement
  to a DynamicAgentDef with source=Federation, operator_key_seed=None
- Add approve_federation_agent Tauri command: verifies signature via
  verify_key_from_did + ad.verify(), persists to SQLite, registers in
  live local registry — BM25 picks it up on next IntentIndex build
- Add 6 unit tests covering all branches

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…dler

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Proves that ad_to_federation_def() output is immediately visible to
IntentIndex (BM25) — the core invariant that closes the federation-agent
routing gap.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

toadkicker has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 24, 2026

Benchmark Regression Report

PAP Protocol Benchmark Regression Check
========================================
Baseline: .bench-baseline/baseline.json
Threshold: 55%

  ed25519_keypair_generation                19.7 µs  (baseline: 17.7 µs, +11.6%)  [ok]
  did_key_derivation                         1.5 µs  (baseline: 1.3 µs, +17.6%)  [ok]
  mandate_create_sign                       23.9 µs  (baseline: 20.8 µs, +14.8%)  [ok]
  mandate_chain_verify_depth3              159.4 µs  (baseline: 120.6 µs, +32.1%)  [ok]
  sd_jwt_issue_5claims                      27.7 µs  (baseline: 24.0 µs, +15.5%)  [ok]
  sd_jwt_verify_disclose_3of5               54.2 µs  (baseline: 41.4 µs, +30.7%)  [ok]
  session_open_full_lifecycle              112.1 µs  (baseline: 93.0 µs, +20.5%)  [ok]
  receipt_create_cosign                     48.5 µs  (baseline: 41.6 µs, +16.5%)  [ok]
  federation_announce_local                 62.1 µs  (baseline: 51.5 µs, +20.4%)  [ok]


P99 Tail-Latency Check
----------------------
Results: target/p99_results.json
Threshold: 50%

  session_open_full_lifecycle(p99)         120.2 µs  (baseline: 500.0 µs, -75.9%)  [ok]
  mandate_chain_verify_depth3(p99)         170.6 µs  (baseline: 480.0 µs, -64.4%)  [ok]
  receipt_create_cosign(p99)                56.2 µs  (baseline: 210.0 µs, -73.2%)  [ok]

All benchmarks within 55% of baseline.

Threshold: 10% regression vs baseline from main

…ines

- examples/intent-routing: remove `&` from `agent_op.did()` call
  (clippy::needless_borrows_for_generic_args)
- cargo fmt applied to papillon and pap-intent-routing packages

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

toadkicker has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

Two test helpers in commands/agents.rs passed &kp.did() where kp.did()
already returns a String — the borrow is redundant since String: Into<String>.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

toadkicker has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@toadkicker toadkicker merged commit 910246b into main Apr 24, 2026
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant