Skip to content

Commit 107b417

Browse files
authored
docs: close remaining Agent Ready warnings
Close #29 by adding glossary discovery, last_updated metadata, stronger static text density, verified visual assets, and tests while preserving Safe Agent API behavior.
1 parent aa1409e commit 107b417

5 files changed

Lines changed: 139 additions & 1 deletion

File tree

assets/demo/safe-agent-demo.gif

93.4 KB
Loading
71.5 KB
Loading

examples/safe-agent-api/app/discovery.py

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
- [OpenAPI]({PUBLIC_URL}/openapi.json): machine-readable API schema
1717
- [Swagger UI]({PUBLIC_URL}/docs): interactive API documentation
1818
- [Playground Markdown]({PUBLIC_URL}/index.md): text-first description of the demo
19+
- [Glossary]({PUBLIC_URL}/glossary): definitions for the safety terms used by the demo
1920
- [Source]({SOURCE_URL}): MIT-licensed source code and contribution workflow
2021
2122
## Safety model
@@ -71,6 +72,7 @@
7172
- [OpenAPI / Swagger]({PUBLIC_URL}/docs)
7273
- [OpenAPI JSON]({PUBLIC_URL}/openapi.json)
7374
- [Markdown mirror]({PUBLIC_URL}/index.md)
75+
- [Glossary]({PUBLIC_URL}/glossary)
7476
- [LLM discovery]({PUBLIC_URL}/llms.txt)
7577
- [Agent instructions]({PUBLIC_URL}/AGENTS.md)
7678
- [Source code]({SOURCE_URL})
@@ -125,6 +127,7 @@
125127
canonical: {PUBLIC_URL}/
126128
version: {RELEASE_VERSION}
127129
last_modified: {LAST_MODIFIED}
130+
last_updated: {LAST_MODIFIED}
128131
---
129132
130133
# Safe Agent Playground
@@ -161,6 +164,17 @@
161164
model suggestion -> policy -> approval -> execution -> audit -> correlation
162165
```
163166
167+
## Glossary
168+
169+
- **Model suggestion:** an action proposed by an AI model; it has no execution authority by itself.
170+
- **Tool policy:** deterministic application logic that allows or denies a proposed tool invocation.
171+
- **Human approval:** an explicit approval signal required before selected sensitive actions can execute.
172+
- **Tenant isolation:** the rule that an actor may only operate on resources within the permitted tenant boundary.
173+
- **Audit event:** a structured record of the decision, execution state, reason, and correlation identifier.
174+
- **Correlation ID:** the identifier used to connect the request, policy decision, execution result, and audit record.
175+
176+
Full terminology reference: {PUBLIC_URL}/glossary
177+
164178
## API
165179
166180
- [Swagger]({PUBLIC_URL}/docs)
@@ -170,6 +184,7 @@
170184
## Sitemap
171185
172186
- [Canonical Playground]({PUBLIC_URL}/)
187+
- [Glossary]({PUBLIC_URL}/glossary)
173188
- [Agent discovery]({PUBLIC_URL}/llms.txt)
174189
- [Agent instructions]({PUBLIC_URL}/AGENTS.md)
175190
- [Human-readable sitemap]({PUBLIC_URL}/sitemap.md)
@@ -179,6 +194,76 @@
179194
{SOURCE_URL}
180195
"""
181196

197+
GLOSSARY_MD = f"""---
198+
title: Safe Agent Playground Glossary
199+
description: Definitions for the production-safety terms used by Safe Agent Playground.
200+
canonical: {PUBLIC_URL}/glossary
201+
last_updated: {LAST_MODIFIED}
202+
---
203+
204+
# Safe Agent Playground Glossary
205+
206+
## Model suggestion
207+
An action proposed by a model. A suggestion is input to policy evaluation and never grants execution authority by itself.
208+
209+
## Tool policy
210+
Deterministic application logic that evaluates a proposed tool action against tenant scope, approval requirements, and disabled-action rules.
211+
212+
## Human approval
213+
An explicit approval signal required for selected sensitive tools. Approval is necessary where policy requires it, but approval does not override a policy that disables an action.
214+
215+
## Tenant isolation
216+
The boundary that prevents an actor in one tenant from operating on a resource that belongs to another tenant.
217+
218+
## Audit event
219+
A structured record capturing the correlation ID, actor tenant, resource tenant, tool, policy decision, execution state, reason, and approval state.
220+
221+
## Correlation ID
222+
A request identifier used to connect a user-visible request with its policy decision, execution result, and audit record.
223+
224+
## Destructive action
225+
An operation that can delete or irreversibly change data. The public demo deliberately blocks destructive execution even when human approval is present.
226+
227+
## Related resources
228+
- [Live Playground]({PUBLIC_URL}/)
229+
- [OpenAPI]({PUBLIC_URL}/openapi.json)
230+
- [Agent instructions]({PUBLIC_URL}/AGENTS.md)
231+
- [Source]({SOURCE_URL})
232+
"""
233+
234+
GLOSSARY_HTML = f'''<!doctype html>
235+
<html lang="en">
236+
<head>
237+
<meta charset="utf-8" />
238+
<meta name="viewport" content="width=device-width,initial-scale=1" />
239+
<title>Safe Agent Playground Glossary</title>
240+
<meta name="description" content="Definitions for tenant isolation, tool policy, human approval, audit events, correlation IDs, and other Safe Agent Playground terms." />
241+
<meta name="robots" content="index, follow, max-snippet:-1, max-image-preview:large" />
242+
<link rel="canonical" href="{PUBLIC_URL}/glossary" />
243+
<link rel="describedby" href="/llms.txt" />
244+
<link rel="alternate" type="text/markdown" href="/glossary.md" />
245+
<meta property="og:title" content="Safe Agent Playground Glossary" />
246+
<meta property="og:description" content="Definitions for the production-safety terms used by Safe Agent Playground." />
247+
<meta property="og:type" content="website" />
248+
<meta property="og:url" content="{PUBLIC_URL}/glossary" />
249+
<style>body{{margin:0;font:16px/1.65 system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;background:#08111f;color:#e8eef7}}main{{max-width:820px;margin:auto;padding:44px 20px 72px}}a{{color:#68a7ff}}h1{{font-size:42px;line-height:1.1}}h2{{margin-top:30px}}p{{color:#c6d2e1}}</style>
250+
</head>
251+
<body>
252+
<main>
253+
<p><a href="/">← Back to Safe Agent Playground</a></p>
254+
<h1>Safe Agent Playground Glossary</h1>
255+
<p>This glossary defines the production-safety terms used by the Playground so readers, search systems, and AI agents can resolve the architecture consistently.</p>
256+
<h2>Model suggestion</h2><p>An action proposed by a model. It is evaluated as untrusted input and never grants execution authority by itself.</p>
257+
<h2>Tool policy</h2><p>Deterministic application logic that evaluates tenant scope, approval requirements, and disabled-action rules before execution.</p>
258+
<h2>Human approval</h2><p>An explicit approval signal required for selected sensitive operations. Approval can satisfy a policy requirement but cannot bypass a policy that disables an action.</p>
259+
<h2>Tenant isolation</h2><p>The boundary preventing an actor associated with one tenant from operating on resources belonging to another tenant.</p>
260+
<h2>Audit event</h2><p>A structured record of the policy decision and execution state, including reason, tenant context, approval state, and correlation identifier.</p>
261+
<h2>Correlation ID</h2><p>A request identifier used to connect a request with its policy decision, execution result, and audit event.</p>
262+
<h2>Destructive action</h2><p>An operation capable of irreversible or high-impact change. The public demo blocks destructive execution even when human approval is present.</p>
263+
</main>
264+
</body>
265+
</html>'''
266+
182267
HEAD_DISCOVERY_HTML = f'''\n <meta name="description" content="Runnable open-source Safe Agent Playground demonstrating tenant isolation, deterministic tool policy, human approval, audit events and correlation IDs for AI-agent execution." />\n <meta name="robots" content="index, follow, max-snippet:-1, max-image-preview:large" />\n <link rel="canonical" href="{PUBLIC_URL}/" />\n <link rel="describedby" href="/llms.txt" />\n <link rel="alternate" type="text/markdown" href="/index.md" />\n <meta property="og:title" content="Safe Agent Playground" />\n <meta property="og:description" content="Try deterministic agent-tool authorization, human approvals, tenant isolation and audit correlation in a runnable FastAPI demo." />\n <meta property="og:type" content="website" />\n <meta property="og:url" content="{PUBLIC_URL}/" />\n <meta property="og:image" content="{SOCIAL_IMAGE_URL}" />\n <meta name="twitter:card" content="summary_large_image" />\n <meta name="twitter:title" content="Safe Agent Playground" />\n <meta name="twitter:description" content="Runnable open-source demo for AI-agent tool authorization boundaries." />\n <meta name="twitter:image" content="{SOCIAL_IMAGE_URL}" />\n <script type="application/ld+json">{{"@context":"https://schema.org","@type":"SoftwareApplication","name":"Safe Agent Playground","headline":"Safe Agent Playground","description":"Runnable open-source demo for AI-agent tool authorization boundaries.","url":"{PUBLIC_URL}/","dateModified":"{LAST_MODIFIED}","softwareVersion":"{RELEASE_VERSION}","applicationCategory":"DeveloperApplication","operatingSystem":"Web","codeRepository":"{SOURCE_URL}"}}</script>\n'''
183268

184-
DISCOVERY_BODY_HTML = f'''\n <section class="card" style="margin-top:20px" aria-labelledby="why-title">\n <h2 id="why-title">Why this demo exists</h2>\n <p>Many AI-agent examples demonstrate how a model selects or calls a tool, but production systems need a separate authorization boundary. This Playground makes that boundary visible: tenant scope is checked first, sensitive actions can require human approval, destructive actions remain blocked, and every decision can be correlated with an audit event.</p>\n <h3>What to evaluate</h3>\n <p>Try an allowed same-tenant read, then change the resource tenant and observe the denial. Compare a notification request before and after human approval. Finally, try the destructive delete scenario and verify that approval alone cannot bypass a policy that disables the tool. The purpose is not to simulate intelligence; it is to make execution policy deterministic, inspectable, testable, and independent from model persuasion.</p>\n <p>Machine-readable resources are available through <a href="/openapi.json">OpenAPI</a>, <a href="/llms.txt">llms.txt</a>, <a href="/AGENTS.md">AGENTS.md</a>, and the <a href="/index.md">Markdown mirror</a>.</p>\n </section>\n'''
269+
DISCOVERY_BODY_HTML = f'''\n <section class="card" style="margin-top:20px" aria-labelledby="why-title">\n <h2 id="why-title">Why this demo exists</h2>\n <p>Many AI-agent examples demonstrate how a model selects or calls a tool, but production systems need a separate authorization boundary. This Playground makes that boundary visible: tenant scope is checked first, sensitive actions can require human approval, destructive actions remain blocked, and every decision can be correlated with an audit event.</p>\n <h3>What to evaluate</h3>\n <p>Try an allowed same-tenant read, then change the resource tenant and observe the denial. Compare a notification request before and after human approval. Finally, try the destructive delete scenario and verify that approval alone cannot bypass a policy that disables the tool. The purpose is not to simulate intelligence; it is to make execution policy deterministic, inspectable, testable, and independent from model persuasion.</p>\n <h3>Why the boundary matters</h3>\n <p>Agent systems become safer when model output is treated as a proposal rather than a permission grant. A separate policy layer can enforce tenant isolation, require approval for sensitive capabilities, disable destructive tools, and record the decision independently of the model's wording. That separation makes the behavior easier to test, audit, review, and reproduce across model providers.</p>\n <p>The demo intentionally performs simulated actions only, so visitors can inspect an allowed execution and several denial paths without credentials, private data, or external side effects. See the <a href="/glossary">glossary</a> for definitions of model suggestion, tool policy, human approval, tenant isolation, audit event, correlation ID, and destructive action.</p>\n <p>Machine-readable resources are available through <a href="/openapi.json">OpenAPI</a>, <a href="/llms.txt">llms.txt</a>, <a href="/AGENTS.md">AGENTS.md</a>, and the <a href="/index.md">Markdown mirror</a>.</p>\n </section>\n'''

examples/safe-agent-api/app/main.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
from app.discovery import (
55
AGENTS_MD,
66
DISCOVERY_BODY_HTML,
7+
GLOSSARY_HTML,
8+
GLOSSARY_MD,
79
HEAD_DISCOVERY_HTML,
810
LLMS_FULL_TXT,
911
LLMS_TXT,
@@ -65,6 +67,33 @@ def playground(request: Request) -> Response:
6567
)
6668

6769

70+
@app.get("/glossary", response_class=HTMLResponse, include_in_schema=False)
71+
def glossary() -> HTMLResponse:
72+
return HTMLResponse(
73+
GLOSSARY_HTML,
74+
headers={
75+
"Cache-Control": "public, max-age=300",
76+
"Content-Security-Policy": "default-src 'self'; style-src 'unsafe-inline'; frame-ancestors 'none'",
77+
"Link": '</llms.txt>; rel="describedby", </glossary.md>; rel="alternate"; type="text/markdown"',
78+
"Referrer-Policy": "no-referrer",
79+
"X-Content-Type-Options": "nosniff",
80+
"X-Robots-Tag": "index, follow, max-snippet:-1, max-image-preview:large",
81+
},
82+
)
83+
84+
85+
@app.get("/glossary.md", response_class=PlainTextResponse, include_in_schema=False)
86+
def glossary_md() -> PlainTextResponse:
87+
return PlainTextResponse(
88+
GLOSSARY_MD,
89+
media_type="text/markdown",
90+
headers={
91+
"Link": '</glossary>; rel="canonical", </sitemap.md>; rel="sitemap"',
92+
"X-Robots-Tag": "index, follow, max-snippet:-1, max-image-preview:large",
93+
},
94+
)
95+
96+
6897
@app.get("/health")
6998
def health() -> dict[str, str]:
7099
return {"status": "ok", "service": "safe-agent-api", "version": RELEASE_VERSION}

examples/safe-agent-api/tests/test_api.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ def test_playground_is_public_and_self_contained() -> None:
1111
assert "Safe Agent Playground" in response.text
1212
assert "/v1/run-demo" in response.text
1313
assert "Why this demo exists" in response.text
14+
assert "Why the boundary matters" in response.text
15+
assert 'href="/glossary"' in response.text
1416
assert 'rel="canonical"' in response.text
1517
assert 'rel="describedby" href="/llms.txt"' in response.text
1618
assert 'property="og:title"' in response.text
@@ -32,6 +34,7 @@ def test_root_supports_markdown_content_negotiation() -> None:
3234
assert response.headers["content-type"].startswith("text/markdown")
3335
assert "# Safe Agent Playground" in response.text
3436
assert "## Sitemap" in response.text
37+
assert "## Glossary" in response.text
3538
assert 'rel="canonical"' in response.headers["link"]
3639

3740

@@ -52,6 +55,7 @@ def test_discovery_documents_are_public() -> None:
5255
assert "# Safe Agent Playground" in llms.text
5356
assert "/openapi.json" in llms.text
5457
assert "/index.md" in llms.text
58+
assert "/glossary" in llms.text
5559

5660
full = client.get("/llms-full.txt")
5761
assert full.status_code == 200
@@ -73,6 +77,7 @@ def test_discovery_documents_are_public() -> None:
7377
sitemap_md = client.get("/sitemap.md")
7478
assert sitemap_md.status_code == 200
7579
assert sitemap_md.headers["content-type"].startswith("text/markdown")
80+
assert "/glossary" in sitemap_md.text
7681

7782
agents = client.get("/AGENTS.md")
7883
assert agents.status_code == 200
@@ -88,10 +93,29 @@ def test_discovery_documents_are_public() -> None:
8893
assert markdown.text.startswith("---\n")
8994
assert "canonical: https://safe-agent-playground.onrender.com/" in markdown.text
9095
assert "last_modified: 2026-09-07" in markdown.text
96+
assert "last_updated: 2026-09-07" in markdown.text
9197
assert "## Scenarios" in markdown.text
98+
assert "## Glossary" in markdown.text
9299
assert "## Sitemap" in markdown.text
93100

94101

102+
def test_glossary_has_html_and_markdown_versions() -> None:
103+
html = client.get("/glossary")
104+
assert html.status_code == 200
105+
assert html.headers["content-type"].startswith("text/html")
106+
assert "Safe Agent Playground Glossary" in html.text
107+
assert 'rel="canonical" href="https://safe-agent-playground.onrender.com/glossary"' in html.text
108+
assert 'rel="alternate" type="text/markdown" href="/glossary.md"' in html.text
109+
assert "Tenant isolation" in html.text
110+
111+
markdown = client.get("/glossary.md")
112+
assert markdown.status_code == 200
113+
assert markdown.headers["content-type"].startswith("text/markdown")
114+
assert "last_updated: 2026-09-07" in markdown.text
115+
assert "## Tool policy" in markdown.text
116+
assert 'rel="canonical"' in markdown.headers["link"]
117+
118+
95119
def test_read_is_allowed_in_same_tenant() -> None:
96120
response = client.post(
97121
"/v1/tool-check",

0 commit comments

Comments
 (0)