docs: 5-minute MCP tutorial + neighboring-projects boundaries table#80
Merged
Conversation
Implements the documentation/onboarding group identified during triage: #46 (tutorial) + #71 (boundaries doc). One PR because both edits land in README/docs and share the "first-time reader" goal. #46 — Tutorial - New docs/tutorial.md walks a new reader from `pip install` through registration, principals, grants, summary/table/handle_only modes, handle expansion, a policy denial with stable reason_code, and an audit via explain(). The MCP section points at docs/integrations.md rather than forking a second source of truth on MCP. - New examples/tutorial.py is the runnable companion using only InMemoryDriver (offline, zero external deps). Demonstrates that `email` never reaches the LLM-safe Frame across all three response modes. Wired into the Makefile `example` target and the CI Examples step on Python 3.10/3.11/3.12. #71 — Neighboring-projects boundaries - README "How this relates to neighboring projects" section: neutral table covering agent-kernel (this repo, embeddable runtime), AgentFence (external CLI/proxy gate), contextweaver (context compilation), ChainWeaver (deterministic flow orchestrator), and weaver-spec (specification + conformance suite). - "When *not* to use this" callout. - README quickstart now points new readers at docs/tutorial.md. Verification: ruff format/check clean (49 files); pytest 450 passed; all four examples run cleanly. Pre-existing mypy notes (pydantic stubs, adapters/_base.py) verified to predate this branch via git stash. Closes #46 Closes #71 https://claude.ai/code/session_01E9jQWivDjJuYMXEFEq9Pq7
There was a problem hiding this comment.
Pull request overview
Adds first-time-reader onboarding material: a runnable 5‑minute tutorial (offline + optional MCP section) and a README section clarifying boundaries vs neighboring Weaver ecosystem projects. It also wires the new tutorial example into make example and CI so it stays runnable.
Changes:
- Add
docs/tutorial.mdand a companion runnableexamples/tutorial.pycovering register → grant → invoke → expand → explain, with an MCP “swap the driver” section. - Update
README.mdwith a “neighboring projects” boundaries table + minimal architecture diagram + “when not to use this” guidance, plus a quick pointer to the tutorial. - Run the new tutorial example in
make exampleand the GitHub Actions CI workflow; document both additions inCHANGELOG.md.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Adds tutorial pointer and boundaries/architecture section for new readers. |
| Makefile | Includes examples/tutorial.py in the example target. |
| examples/tutorial.py | New runnable tutorial script using InMemoryDriver, executed by CI. |
| docs/tutorial.md | New 5‑minute walkthrough doc, with optional MCP driver swap guidance. |
| CHANGELOG.md | Adds Unreleased entries for the tutorial and boundaries section. |
| .github/workflows/ci.yml | Runs examples/tutorial.py as part of the Examples step. |
Three review-comment fixes; all three were valid.
examples/tutorial.py:173 — the leakage line printed but never failed
the run. Replaced with `assert leaked == []` so a future firewall
regression on `allowed_fields` enforcement breaks the build (matches
the PR description's "fail loudly" claim).
docs/tutorial.md:170 — removed the false claim that handle expansion
applies projection "on top of allowed_fields, never around it".
Empirically verified the gap: `kernel.expand(handle, query={"fields":
["email"]})` returns the email even when `allowed_fields=["id"]`,
because `kernel.invoke` stores `raw_result.data` unredacted and
`HandleStore.expand` has no knowledge of the original grant's
`allowed_fields`. New paragraph describes today's behavior accurately
and points readers at issue #76 / PR #79 (the in-flight grant-constraint
work) instead of overpromising.
CHANGELOG.md:18 — tutorial only covers the three LLM-safe response
modes (summary / table / handle_only); admin-only `raw` mode is
mentioned but not exercised. Reworded to match.
Verification: ruff format/check clean; pytest 450 passed; tutorial.py
exits 0.
https://claude.ai/code/session_01E9jQWivDjJuYMXEFEq9Pq7
After merging main (which includes #76 grant-constraint enforcement), HandleStore.expand() rejects expansion without a matching principal. Update tutorial example and docs to pass principal=reader/alice.
Owner's b1e058b added principal=alice to the kernel.expand call and shortened the docs callout to describe the now-current behavior. This commit layers one additional thing on top: a positive proof that the new grant-constraint enforcement actually fires. - examples/tutorial.py: after the successful expand, request a field outside allowed_fields ('email') and assert that HandleConstraintViolation is raised with reason_code 'handle_constraint_violation'. Without this, a future regression on the #76 expand path could silently leak data and the tutorial would still appear to pass — same logic as the leak == [] assertion the Copilot review asked for on the table-mode step. - docs/tutorial.md section 6: add the matching disallowed-field code block under the security-boundary callout so the doc and the example stay in lockstep, plus a one-line note that limit/scope/principal mismatches use the same shape and list their reason_codes. Verification: ruff format/check clean; pytest 483 passed; tutorial.py prints 'blocked disallowed field: reason_code=handle_constraint_violation'. https://claude.ai/code/session_01E9jQWivDjJuYMXEFEq9Pq7
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the documentation/onboarding group identified during triage:
#46 (5-minute tutorial) + #71 (neighboring-projects boundaries). One PR
because both deliverables land in
README.md/docs/and serve the samefirst-time-reader goal — splitting them would just churn the same files twice.
What changed
#46 — Tutorial
docs/tutorial.mdwalks a new reader frompip installthroughregistration, principals, grants, all three LLM-safe response modes
(
summary/table/handle_only), principal-bound handle expansion, apolicy denial with a stable
reason_code, and an audit viaexplain().The MCP section points at
docs/integrations.mdrather than forking asecond source of truth on MCP transports.
examples/tutorial.pyis the runnable companion using onlyInMemoryDriver— offline, zero external dependencies. Demonstratesexplicitly that
emailnever reaches the LLM-safe Frame across any ofthe response modes (
PII fields leaked into Frame: 0).exampletarget and the CI Examples step so thetutorial is exercised on Python 3.10/3.11/3.12 every push.
docs/tutorial.md.#71 — Neighboring-projects boundaries
comparison table covering
agent-kernel(this repo, embeddableruntime),
AgentFence(external CLI/proxy gate),contextweaver(context compilation library),
ChainWeaver(deterministic floworchestrator), and
weaver-spec(specification + conformance suite).project when agent-kernel is the wrong tool.
Misc
CHANGELOG.md[Unreleased]entries for both additions.mainto pick up Add redaction boundary tests for frames, raw results, and traces #74/Add policy checks for memory read and write actions #75/security: enforce grant constraints during handle expansion #76 (grant-constraint enforcement);tutorial's
kernel.expand()call now passesprincipal=readerand thesecurity callout in
docs/tutorial.mdreflects the landed behavior.Why
From triage on
claude/triage-issues-Yzss7: of the 9 open issues notalready covered by an open PR, #46 and #71 were the most coherent pair —
both unblocked (MCP Driver shipped via #66 unblocked #46), both fully
closeable by the same PR, both share
README.md, and the implementationrisk is the lowest of any plausible group. The marketplace cluster
(#52 + #49) had similar coherence but #49 was explicitly kept open as a
tracker, so that group's closure yield was lower.
How verified
ruff format --check src/ tests/ examples/— 49 files already formatted.ruff check src/ tests/ examples/— All checks passed.python -m pytest -q— 483 passed in 8.34s (includes tests frommerged Add redaction boundary tests for frames, raw results, and traces #74/Add policy checks for memory read and write actions #75/security: enforce grant constraints during handle expansion #76).
basic_cli.py,billing_demo.py,http_driver_demo.py,tutorial.py) run cleanly end-to-end.PII fields leaked into Frame: 0againstthe table-mode preview — that line will fail loudly if the firewall
ever regresses on
allowed_fieldsenforcement.pydanticstub resolution,adapters/_base.pyAnyreturns) verified to predate this branch viagit stash— nosrc/files were touched in this PR.Tradeoffs / risks
runtime).
one-line-at-a-time against the existing README's tone and against the
repo names; a reviewer with first-hand knowledge of each sister repo
should sanity-check the wording.
docs/integrations.mdrather than duplicating transport details, sothere is exactly one canonical source for the MCP code patterns.
Scope notes
Two issues, one PR. Adjacent issues left untouched: #38 (OTel), #45
(namespaces), #47 (streaming firewall), #49/#51/#52 (marketplace), #68
(decompose
policy_dsl.py+ dry-run driver coverage). One follow-upworth noting: #46 still carries a stale
blockedlabel (its blocker,MCP Driver, landed in #66) — happy to drop the label in a follow-up if
desired.
Closes
Closes #46
Closes #71