Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions src/components/RelatedPagesInline.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
/**
* Quiet "See also" list rendered at the end of the article body, above
* Starlight's Prev/Next pagination. Reads as a caption, not navigation —
* complements the linear Prev/Next with lateral topical jumps.
*
* Display cap (4) differs from the headless cap (10) in related-docs.ts:
* humans can only scan a handful of links before it becomes noise.
*/
import { getCollection } from 'astro:content'
import { relatedUserGuideFor } from '../util/related-docs'
import { pathWithBase } from '../util/links'

const MAX_DISPLAY = 4

const { starlightRoute } = Astro.locals
const entry = starlightRoute.entry
// Non-docs routes (blog pages, StarlightPage splashes) flow through
// MarkdownContent too — short-circuit before calling into the util.
const related = entry.collection === 'docs'
? relatedUserGuideFor(entry, await getCollection('docs')).slice(0, MAX_DISPLAY)
: []
---

{related.length > 0 && (
<aside class="related-inline" aria-label="Related pages">
<div class="related-inline__label">See also</div>
<ul class="related-inline__list">
{related.map((link) => (
<li>
<a href={pathWithBase(`/${link.slug}/`)}>{link.title}</a>
</li>
))}
</ul>
</aside>
)}

<style>
.related-inline {
margin-top: 2.5rem;
padding-top: 1rem;
border-top: 1px solid var(--sl-color-hairline);
line-height: 1.4;
}

.related-inline__label {
font-size: 0.875rem;
font-weight: 700;
letter-spacing: 0.02em;
color: var(--sl-color-white);
margin-bottom: 0.5rem;
}

.related-inline__list {
list-style: none;
padding: 0;
margin: 0;
}

.related-inline__list li {
margin: 0;
}

.related-inline__list a {
display: inline-block;
padding: 0.0625rem 0;
font-size: 0.875rem;
color: var(--sl-color-text-accent);
text-decoration: none;
}

.related-inline__list a:hover {
text-decoration: underline;
}
</style>
38 changes: 37 additions & 1 deletion src/components/overrides/Head.astro
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
* and structured data (JSON-LD).
* See ARCHITECTURE.md for details.
*/
import { getCollection } from 'astro:content'
import SiteScripts from '../SiteScripts.astro'
import { baseSchemas } from '../../util/structured-data'
import { relatedUserGuideFor } from '../../util/related-docs'

const { head } = Astro.locals.starlightRoute
const route = Astro.locals.starlightRoute
Expand Down Expand Up @@ -60,14 +62,48 @@ const breadcrumbItems = pathSegments.map((segment, i) => {
}
})

// TechArticle node for docs pages with tags or sourceLinks.
// Reaches HTML-only crawlers that don't follow the llms.txt convention.
const entry = route.entry
// Non-docs routes (blog authors/tags pages, etc.) flow through Starlight too
// but their synthetic entry.data has no `tags` field — guard with ??.
const tags = entry.data.tags ?? []
const sourceLinks = entry.data.sourceLinks ?? []
let techArticle: Record<string, unknown> | null = null
if (tags.length > 0 || sourceLinks.length > 0) {
Comment thread
notowen333 marked this conversation as resolved.
const related = tags.length > 0
? relatedUserGuideFor(entry, await getCollection('docs'))
: []
techArticle = {
"@type": "TechArticle",
"headline": entry.data.title,
"url": siteUrl + Astro.url.pathname,
...(tags.length > 0 ? { "keywords": tags.join(', ') } : {}),
...(entry.data.description ? { "description": entry.data.description } : {}),
...(related.length > 0
? { "relatedLink": related.map((r) => siteUrl + '/' + r.slug + '/') }
: {}),
...(sourceLinks.length > 0
? {
"isBasedOn": sourceLinks.map((s: { repo: string, path: string }) => ({
"@type": "SoftwareSourceCode",
"codeRepository": `https://github.com/strands-agents/${s.repo}`,
"url": `https://github.com/strands-agents/${s.repo}/blob/main/${s.path}`,
})),
}
: {}),
}
}

const structuredData = {
"@context": "https://schema.org",
"@graph": [
...baseSchemas(siteUrl),
{
"@type": "BreadcrumbList",
"itemListElement": breadcrumbItems
}
},
...(techArticle ? [techArticle] : []),
]
}
---
Expand Down
2 changes: 2 additions & 0 deletions src/components/overrides/MarkdownContent.astro
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import '@astrojs/starlight/style/markdown.css';
import CommunityContributionAside from '../CommunityContributionAside.astro';
import LanguageSupportAside from '../LanguageSupportAside.astro';
import ExperimentalAside from '../ExperimentalAside.astro';
import RelatedPagesInline from '../RelatedPagesInline.astro';

const { starlightRoute } = Astro.locals;
const { languages, community, experimental } = starlightRoute.entry.data;
Expand All @@ -15,4 +16,5 @@ const { languages, community, experimental } = starlightRoute.entry.data;
contextualizes the page, and language support is listed in the community catalog table instead. */}
{languages && !community && <LanguageSupportAside languages={languages} />}
<slot />
<RelatedPagesInline />
</div>
25 changes: 25 additions & 0 deletions src/config/tags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import fs from 'node:fs'
import { fileURLToPath } from 'node:url'
import yaml from 'js-yaml'
import { z } from 'astro/zod'

const TAGS_YML = fileURLToPath(new URL('./tags.yml', import.meta.url))

function loadAllowedTags(): readonly string[] {
const raw = yaml.load(fs.readFileSync(TAGS_YML, 'utf-8'))
if (!Array.isArray(raw) || !raw.every((t): t is string => typeof t === 'string')) {
throw new Error(`[tags] ${TAGS_YML} must be a flat YAML list of strings`)
}
const deduped = Array.from(new Set(raw))
if (deduped.length !== raw.length) {
const dupes = raw.filter((t, i) => raw.indexOf(t) !== i)
throw new Error(`[tags] ${TAGS_YML} contains duplicate entries: ${[...new Set(dupes)].join(', ')}`)
}
return deduped
}

export const ALLOWED_TAGS = loadAllowedTags()

export const TagSchema = z.enum(ALLOWED_TAGS as readonly [string, ...string[]])

export type Tag = z.infer<typeof TagSchema>
42 changes: 42 additions & 0 deletions src/config/tags.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Allowed tag vocabulary for user-guide pages.
#
# Tags drive the build-time "Related pages" block. A page's `tags` frontmatter
# is validated against this list by the docs schema (src/content.config.ts) —
# unknown tags fail the build.
#
# Scoring: `more shared tags = more related`. Aim for 2–4 tags per page drawn
# from different axes below so pages naturally connect along topic, capability,
# lifecycle, and audience dimensions.
#
# Adding a tag = PR editing this file in the same change that first uses it.

# Topics / domains — specific products, protocols, data types
Comment thread
notowen333 marked this conversation as resolved.
- agentcore
- aws
- bedrock
- guardrails
- mcp
- pii

# Capabilities — what the page teaches the reader to do
- conversation-management
- hooks
- multi-agent
- retry
- session-management
- state
- streaming
- structured-output
- tools

# Lifecycle / practice — where in the dev lifecycle this sits
- deployment
- evaluation
- observability
- production
- quickstart
- safety

# Audience — language-specific pages
- python
- typescript
12 changes: 12 additions & 0 deletions src/content.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { docsSchema } from '@astrojs/starlight/schema'
import { slug as githubSlug } from 'github-slugger'
import { glob, file } from 'astro/loaders'
import { normalizePathToSlug } from './util/links'
import { TagSchema } from './config/tags'

const authorSchema = z.object({
name: z.string(),
Expand All @@ -14,6 +15,12 @@ const authorSchema = z.object({
avatar: z.string().optional(),
})

export const sourceLinkSchema = z.object({
repo: z.enum(['sdk-python', 'sdk-typescript']),
path: z.string(),
})
export type SourceLink = z.infer<typeof sourceLinkSchema>

const blogSchema = z.object({
title: z.string(),
date: z.coerce.date(),
Expand Down Expand Up @@ -89,6 +96,11 @@ export const collections = {
description: z.string().optional(),
// Array of slugs that should redirect to this page (e.g., old URLs)
redirectFrom: z.array(z.string()).optional(),
// Tags from src/config/tags.yml — drive the build-time "Related pages" block
tags: z.array(TagSchema).default([]),
// Pointers to the SDK implementation behind this page. Rendered as an
// "Implementation" section on headless surfaces only (index.md, llms-full.txt).
sourceLinks: z.array(sourceLinkSchema).optional(),
}),
}),
}),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: Conversation Management
tags: [conversation-management]
---

In the Strands Agents SDK, context refers to the information provided to the agent for understanding and reasoning. This includes:
Expand Down
1 change: 1 addition & 0 deletions src/content/docs/user-guide/concepts/agents/hooks.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Hooks
description: "Intercept and customize agent behavior at every step. Hooks let you add logging, validation, guardrails, and custom logic to the agent loop."
tags: [hooks]
---


Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: Retry Strategies
tags: [retry]
Comment thread
notowen333 marked this conversation as resolved.
Outdated
---

Model providers occasionally encounter errors such as rate limits, service unavailability, or network timeouts. By default, the agent retries `ModelThrottledException` failures automatically with exponential backoff and the `Angent.retry_strategy` parameter lets you customize this behavior.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Session Management
description: "Persist agent conversations across sessions. Save and restore chat history, tool state, and context for long-running AI workflows."
tags: [session-management]
---

Session management in Strands Agents provides a robust mechanism for persisting agent state and conversation history across multiple interactions. This enables agents to maintain context and continuity even when the application restarts or when deployed in distributed environments.
Expand Down
1 change: 1 addition & 0 deletions src/content/docs/user-guide/concepts/agents/state.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
title: State Management
sidebar:
label: "State"
tags: [state]
Comment thread
notowen333 marked this conversation as resolved.
Outdated
---

Strands Agents state is maintained in several forms:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Structured Output
description: "Get typed, validated responses from AI agents. Define Pydantic models and Strands returns structured data instead of raw text."
tags: [structured-output]
---

## Introduction
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: BidiAgent
experimental: true
tags: [streaming]
---


Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Events
experimental: true
tags: [streaming]
Comment thread
notowen333 marked this conversation as resolved.
Outdated
---


Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
---
title: Hooks
title: Bidirectional Streaming Hooks
sidebar:
label: "Hooks"
experimental: true
tags: [hooks, streaming]
---


Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Interruptions
experimental: true
tags: [streaming]
---


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: I/O Channels
experimental: true
sidebar:
label: "IO"
tags: [streaming]
---


Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Gemini Live
experimental: true
tags: [streaming]
---


Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Nova Sonic
experimental: true
tags: [streaming, aws, bedrock]
---


Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: OpenAI Realtime
experimental: true
tags: [streaming]
---


Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
---
title: Session Management
title: Bidirectional Streaming Session Management
sidebar:
label: "Session Management"
experimental: true
tags: [session-management, streaming]
---


Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Amazon Bedrock
integrationType: model-provider
tags: [bedrock, aws]
---

Amazon Bedrock is a fully managed service that offers a choice of high-performing foundation models from leading AI companies through a unified API. Strands provides native support for Amazon Bedrock, allowing you to use these powerful models in your agents with minimal configuration.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
title: Amazon Nova
languages: Python
integrationType: model-provider
tags: [aws, bedrock]
---

[Amazon Nova](https://nova.amazon.com/) is a new generation of foundation models with frontier intelligence and industry leading price performance. Generate text, code, and images with natural language prompts. The [`strands-amazon-nova`](https://pypi.org/project/strands-amazon-nova/) package ([GitHub](https://github.com/amazon-nova-api/strands-nova)) provides an integration for the Strands Agents SDK, enabling seamless use of Amazon Nova models.
Expand Down
Loading
Loading