-
Notifications
You must be signed in to change notification settings - Fork 1
Training docs #284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Training docs #284
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughAdds a new "Training" docs section with seven developer modules, a tutorials manifest and helper utilities, switches tutorial APIs to a config-driven flow, and introduces secure path/file utilities used by MDX parsing and file-reading components; includes multiple docs, API, lib, and component updates. Changes
Sequence Diagram(s)sequenceDiagram
participant C as Client
participant API as /api/tutorials
participant LIB as lib/tutorial
participant CFG as content/tutorials.json
participant MDX as MDX parser
participant FS as secure-file (readSecureFile)
C->>API: GET /api/tutorials
API->>LIB: getTutorialsConfig()
LIB->>CFG: read manifest
CFG-->>LIB: tutorials metadata
LIB-->>API: tutorials list (ids/paths)
API->>MDX: parse referenced MDX for metadata/steps (per tutorial)
MDX->>FS: readSecureFile(path, options)
FS-->>MDX: file content / error
MDX-->>API: parsed metadata/steps
API-->>C: 200 OK (filtered tutorials)
alt GET single tutorial
C->>API: GET /api/tutorials/{id}
API->>LIB: getTutorialFilePath(id)
LIB->>CFG: find entry
CFG-->>LIB: path or null
alt not found
LIB-->>API: null
API-->>C: 404 Not Found
else found
LIB-->>API: resolved path
API->>MDX: parse MDX file
MDX->>FS: readSecureFile(path, from?, to?)
FS-->>MDX: content / error
MDX-->>API: parsed content
API-->>C: 200 OK (tutorial content)
end
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
docs | edea5c7 | Oct 19 2025, 06:57 PM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (26)
content/Training/developers/01-introduction-to-agents.mdx (2)
195-206: Add Homebrew install fallback and Windows/Linux notes.Include curl/bash/npm alternatives (and checksum note) for non-macOS setups to avoid blocking Windows/Linux readers.
254-286: Python example: ensure imports shown near usage.The block uses datetime but imports are only shown in a prior block; duplicate the import here for copy/paste friendliness.
+from datetime import datetimecontent/Training/developers/02-anatomy-of-an-agent.mdx (4)
51-53: Python examples: missing datetime import.Multiple snippets call datetime.now() without importing; add
from datetime import datetimein each affected block.+from datetime import datetimeAlso applies to: 61-62
190-205: KV set: avoid JSON-encoding manually in JS.Elsewhere you pass plain objects to KV; here you
JSON.stringify. Standardize on passing objects and let the SDK handle serialization.- await context.kv.set('cache', 'key', JSON.stringify({ data: 'value' })); + await context.kv.set('cache', 'key', { data: 'value' });
207-211: Vector upsert shape inconsistent.Most examples upsert an array of items; this one passes a single object. Align with array form for consistency.
- await context.vector.upsert('docs', { - key: 'doc1', - document: 'AI agents are autonomous systems', - metadata: { category: 'intro' } - }); + await context.vector.upsert('docs', [{ + key: 'doc1', + document: 'AI agents are autonomous systems', + metadata: { category: 'intro' } + }]);
582-621: Weather: non-deterministic temperature via hash().Python’s built-in hash is salted per process, so values vary across runs. Use a stable hash.
- "temperature": 20 + hash(city) % 15, + "temperature": 20 + (abs(zlib.crc32(city.encode())) % 15),Add
import zlibat the top of that code block.Also applies to: 622-626
content/Training/developers/03-agent-memory.mdx (6)
83-106: Python: add required imports and clarify API parameters.This block uses datetime and a similarity threshold; add
from datetime import datetime. Also confirm whethersimilarityis a named arg onvector.searchor part of options.+from datetime import datetime - memories = await context.vector.search( - "user_knowledge", - f"What do I know about user {user_id}?", - limit=5, - similarity=0.7 - ) + memories = await context.vector.search( + "user_knowledge", + f"What do I know about user {user_id}?", + limit=5, + # similarity may belong in an options dict, verify SDK + )
189-205: JS vector.upsert should take an array for consistency.- await context.vector.upsert('conversations', { + await context.vector.upsert('conversations', [{ key: `conv_${new Date().toISOString()}`, document: "User asked about deploying agents in production. " + "They're concerned about costs and scaling. " + "Recommended starting with dev environment.", metadata: { user_id: userId, topic: 'deployment', sentiment: 'cautious', timestamp: new Date().toISOString() } - }); + }]);
218-235: Object storage examples: define variables and import modules.Both blocks reference analysisResults/report_data/userId/json without definitions. Add placeholders or comments so copy/paste works.
+# assume analysis_results and user_id are defined above +from datetime import datetime +import jsonAnd in JS:
+// assume analysisResults and userId are defined aboveAlso applies to: 236-253
740-779: Cleanup agent: undefined helpers and imports.
get_old_sessions,timedelta, andjsonare used but not defined/imported. Add them or annotate as placeholders.+from datetime import datetime, timedelta +import json +# def get_old_sessions(cutoff_date): ...
430-496: KV/vector API consistency in JS.You mix raw objects and JSON strings in
kv.setandvector.upsert. Standardize on raw objects for clarity unless the SDK requires strings.- await context.kv.set('profiles', userId, JSON.stringify(profile)); + await context.kv.set('profiles', userId, profile);
124-159: PII caution in examples.Storing full names/timezones in KV is fine for demos, but add a one-line note about avoiding PII in production tutorials.
content/Training/developers/04-agent-collaboration.mdx (2)
330-350: Handoff guidance vs. earlier “run()” invocation.Elsewhere (Module 5) you show
agent.run(request)which contradicts the “one-way handoff” model here. Add a note explaining when direct invocation is appropriate vs.response.handoff, or refactor the earlier snippet to usehandoff.Also applies to: 351-378
596-641: Summarizer: add datetime import and handle non-array content defensively.+from datetime import datetimeAnd in JS, check
Array.isArray(content)before.slice.Also applies to: 644-687
content/Training/developers/05-guardrails-evals-observability.mdx (3)
60-85: Consistent terminology and unused imports.You import
field_validatorbut don’t use it. Remove or demonstrate a v2 example to avoid confusion.-from pydantic import BaseModel, Field, ValidationError, field_validator +from pydantic import BaseModel, Field, ValidationErrorAlso applies to: 97-117
261-274: Cross-module API naming and invocation style.
- Python uses
context.get_agent(...); other modules usecontext.getAgent(...). Pick one SDK surface across docs.- Replace
await agent.run(request)withresponse.handoff(...)(plus metadata) to stay consistent with the one-way model taught in Module 4, or add a note explicitly distinguishing proxy execution vs. handoff.Also applies to: 283-299
666-686: Observability examples reference undefined vars.Add small preambles defining user_id/data/query or annotate as placeholders to prevent copy/paste errors.
+user_id = request.metadata.get("user_id", "anonymous") +data = {} +query = "retirement planning"JS analogs likewise.
Also applies to: 1012-1066
content/Training/developers/06-deployment-environments.mdx (2)
110-119: MDX JSX comment block may be stripped by the site generator.Replace the JSX comment with a Callout or regular prose to ensure it renders.
-{/* ... long JSX comment ... */} +<Callout type="info"> +Environment-specific settings are configured in the Agentuity web console. Screenshots coming soon. +</Callout>
52-55: Add explicit “staging” placeholder command or remove block.“Deploy to staging (coming soon)” with an empty code block can confuse readers; either show a stub command or remove the fence.
content/Training/developers/07-sandbox-capstone.mdx (2)
101-111: Model IDs and SDK imports: add “verify current model names” note.Anthropic model names change; add a comment to verify the latest model ID and SDK import path before running the sample.
Also applies to: 159-225
250-271: KV.listcontract unclear.
context.kv.list("outcomes", prefix=...)API isn’t introduced elsewhere. Add a brief description or link, or show a pattern using known list/scan semantics.content/Training/index.mdx (1)
21-21: Add trailing newline at EOF.Prevents nitty CI/style failures and improves diffs.
-**For Tech Leads** - Architecture patterns and integration strategies +**For Tech Leads** - Architecture patterns and integration strategies +content/Training/developers/index.mdx (4)
44-46: Add a link (or remove the mention) for Framework Migration Guide.This is a dead-end CTA right now; link it or gate it behind “Coming Soon”.
-Check our Framework Migration Guide for specifics on moving from AWS Bedrock, Google ADK, or Azure AI. +Check our [Framework Migration Guide](../framework-migration) for specifics on moving from AWS Bedrock, Google ADK, or Azure AI. +# If the guide isn't ready, prefer: +# > Coming soon: Framework Migration Guide for moving from AWS Bedrock, Google ADK, or Azure AI.
47-55: Offer a full curriculum TOC for quick navigation.Add a bulleted list linking all seven modules.
## What Makes This Different @@ Ready to dive into the world of AI agents? Let's get started with [Module 1: Introduction to Agents](./01-introduction-to-agents). + +## All Modules +- [Module 1: Introduction to Agents](./01-introduction-to-agents) +- [Module 2: Anatomy of an Agent](./02-anatomy-of-an-agent) +- [Module 3: Agent Memory](./03-agent-memory) +- [Module 4: Agent Collaboration](./04-agent-collaboration) +- [Module 5: Guardrails, Evals, and Observability](./05-guardrails-evals-observability) +- [Module 6: Deployment Environments](./06-deployment-environments) +- [Module 7: Sandbox Capstone](./07-sandbox-capstone)
18-19: Link “OpenTelemetry” to its docs for convenience.Tiny UX boost; optional.
-- Fully observable systems with OpenTelemetry tracing +- Fully observable systems with [OpenTelemetry](https://opentelemetry.io/) tracing
1-4: Consider adding a review/update timestamp in frontmatter.Helps readers assess freshness for a fast-moving topic.
--- title: Developer Training description: Building with Agentuity - Developer Learning Path +lastReviewed: 2025-09-16 ---
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
content/Training/developers/01-introduction-to-agents.mdx(1 hunks)content/Training/developers/02-anatomy-of-an-agent.mdx(1 hunks)content/Training/developers/03-agent-memory.mdx(1 hunks)content/Training/developers/04-agent-collaboration.mdx(1 hunks)content/Training/developers/05-guardrails-evals-observability.mdx(1 hunks)content/Training/developers/06-deployment-environments.mdx(1 hunks)content/Training/developers/07-sandbox-capstone.mdx(1 hunks)content/Training/developers/index.mdx(1 hunks)content/Training/index.mdx(1 hunks)content/meta.json(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-07-23T12:40:34.834Z
Learnt from: CR
PR: agentuity/docs#0
File: agent-docs/.cursor/rules/sdk.mdc:0-0
Timestamp: 2025-07-23T12:40:34.834Z
Learning: Applies to agent-docs/src/agents/**/*.ts : Consider agent communication for complex workflows
Applied to files:
content/Training/developers/04-agent-collaboration.mdx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Workers Builds: docs
🔇 Additional comments (6)
content/meta.json (1)
6-6: Nav addition LGTM.“Training” entry slots cleanly between Guides and Cloud.
content/Training/developers/02-anatomy-of-an-agent.mdx (1)
228-236: Not applicable — no LangChain/OpenAI imports in this snippet.
Lines 228–236 are prose (planning description + OpenAI guide link); the warning about LangChain import paths and pinning versions is misplaced.Likely an incorrect or invalid review comment.
content/Training/developers/05-guardrails-evals-observability.mdx (1)
933-962: Rate limiting: KV get/set is not atomic — race risk.KV get/set can race under concurrent bursts; prefer a server-side atomic counter (e.g., Redis INCR or an atomic KV increment) or serialize updates (Durable Object or compare-and-set loop). If atomic ops aren’t available, document the potential for small overage and consider switching to a store that supports atomic increments.
Applies to: content/Training/developers/05-guardrails-evals-observability.mdx lines 933–962 (also 434–454).content/Training/index.mdx (1)
15-15: Confirmed — ./developers link resolves and "Training" is in nav.content/Training/developers/index.mdx exists; content/meta.json contains "Training" (match at line 6).
content/Training/developers/index.mdx (2)
35-43: Validate module links resolve — files exist; run build/link-checkFiles present: content/Training/developers/01-introduction-to-agents.mdx, 03-agent-memory.mdx, 04-agent-collaboration.mdx, 06-deployment-environments.mdx — links in content/Training/developers/index.mdx (lines 35–43) reference these files. Run the site build or a link-checker to confirm there are no broken links in the generated site.
8-10: Stabilize & cite market-size + IBM referenceFile: content/Training/developers/index.mdx (lines 8–10)
Replace the standalone “$47B by 2030” with a verifiable citation (title, publisher, publish date, and access date). Recent credible estimates vary — Grand View Research: "AI Agents Market Size To Reach $50.31Bn By 2030" (May 6, 2025); MarkNtel Advisors: "AI Agent Market Forecast to Hit USD 42.7 Billion by 2030" (2025); Precedence/GlobeNewswire: 2030 ≈ USD 52.20B (news release July 2, 2025). Either cite one report (with access date, e.g., accessed Sep 16, 2025) or rephrase to a range (≈ $42–52B by 2030) and cite two sources.
Verify the IBM link: confirm it points to the intended IBM Think article (include exact title and publish date + access date). If the intent was to cite Reuters' coverage instead, swap to Reuters — "IBM CEO makes play for AI market and more US investment" (May 6, 2025) — and add full citation/access date.
| history = await context.kv.get("conversations", session_id) | ||
| messages = history.data.json() if history.exists else [] | ||
| # Analyze customer intent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Await missing on .data.json() (Python).
messages = history.data.json() if history.exists else [] should await .data.json().
- messages = history.data.json() if history.exists else []
+ messages = await history.data.json() if history.exists else []📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| history = await context.kv.get("conversations", session_id) | |
| messages = history.data.json() if history.exists else [] | |
| # Analyze customer intent | |
| history = await context.kv.get("conversations", session_id) | |
| messages = await history.data.json() if history.exists else [] | |
| # Analyze customer intent |
🤖 Prompt for AI Agents
In content/Training/developers/07-sandbox-capstone.mdx around lines 118 to 121,
the call to history.data.json() is missing an await; update the assignment to
await history.data.json() when history.exists is true (e.g., messages = await
history.data.json() if history.exists else []) and ensure the surrounding
function is async so awaiting is valid; optionally guard against history or data
being None before awaiting.
| Traditional cloud platforms (AWS Lambda, Google Cloud Functions, Azure Functions) were optimized for: | ||
| - **5ms response times** (agents need minutes or hours to think) | ||
| - **Stateless execution** (agents need persistent memory) | ||
| - **Edge distribution** (agents need GPU proximity) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think if we're going to point out what they are for, then point out what they are not useful for (i.e. how an agent runs and what it needs as a contrast)
| - **AWS** launched Bedrock AgentCore (still in preview) | ||
| - **Google** released their Agent Development Kit (ADK) | ||
| - **Microsoft** is retrofitting Azure with agent capabilities |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We dont need to advertise these here, just saying they're doing this is fine.
| Learn more about the Agent-Native Cloud paradigm in our [Agent-Native Cloud](/Guides/agent-native-cloud) guide. | ||
| </Callout> | ||
|
|
||
| While others retrofit, Agentuity was built from day one specifically for agents. Our agent-native platform puts AI agents at the center of everything we do. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of using "Our", use 3rd person as much as possibl. "Agentuity's agent-native..."
| - **Agent-to-agent communication**: Seamless and secure [channels between agents](/Guides/agent-communication) | ||
| - **Native observability**: Track agent decisions with [built-in tracing](/Guides/agent-tracing) | ||
| - **Automatic scaling**: Based on agent workload, not request count | ||
| - **Framework agnostic**: Run LangChain, CrewAI, or custom agents side by side |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Vercel AI SDK
| Instead of asking "How do we make Lambda work for agents?", we asked "What would infrastructure look like if agents were the only thing that mattered?" | ||
|
|
||
| The result is a platform where: | ||
| - Agents are first-class citizens, not adapted workloads | ||
| - Memory and state are built-in, not bolted on | ||
| - Long-running is the default, not an exception | ||
| - Agent communication is native, not a hack |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The sentence is really good and so are the bullets, but it seems like this and the above "purpose built for agents" should be mashed together.
| # 2. Apply domain rules separately | ||
| prohibited = ['insider', 'guaranteed'] | ||
| if any(term in validated.query.lower() for term in prohibited): | ||
| return response.json({'error': 'Prohibited terms detected'}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While this is fine for a super simple example (which can be stated that way )...it's also not a very agentic way to apply guardrails. I haven't read through this whole thing yet but running thought is showing how to use LLM as judged and guardrails is a very useful pattern.
| }); | ||
|
|
||
| // intent.object is validated and typed | ||
| if (intent.object.confidence > 0.8) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what happens if its not greater than?
| }); | ||
| };`} /> | ||
|
|
||
| ### Performance Best Practices |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I kinda think this should be at the beginning of the course. start with our main value prop of observability and then lean in to performance and such.
| ## The Reality of Enterprise Agent Deployment | ||
|
|
||
| Research shows that [most organizations aren't "agent-ready"](https://www.ibm.com/think/insights/ai-agents-2025-expectations-vs-reality) - they lack the infrastructure, processes, and understanding needed for production agents. When [Salesforce deployed their Agentforce AI agents](https://www.hr-brew.com/stories/2025/03/04/salesforce-ai-agents-reskilling), it required massive organizational change alongside the technology. | ||
|
|
||
| The challenge involves both technical and operational considerations: | ||
| - How do you test non-deterministic agents? | ||
| - How do you safely roll out changes that affect customer interactions? | ||
| - How do you monitor agents that make autonomous decisions? | ||
| - How do you handle failures gracefully when agents are unpredictable? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can remove this since we're deep in to agentuity world now.
| ``` | ||
|
|
||
| ### Production Environment | ||
| **Where agents serve users** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Where agents live" or something like that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
content/Training/developers/01-introduction-to-agents.mdx(1 hunks)content/Training/developers/02-anatomy-of-an-agent.mdx(1 hunks)content/Training/developers/03-agent-memory.mdx(1 hunks)content/Training/developers/04-agent-collaboration.mdx(1 hunks)content/Training/developers/05-observability-guardrails-evals.mdx(1 hunks)content/Training/developers/06-deployment-environments.mdx(1 hunks)content/Training/developers/07-sandbox-capstone.mdx(1 hunks)content/Training/developers/index.mdx(1 hunks)content/Training/index.mdx(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- content/Training/developers/01-introduction-to-agents.mdx
🚧 Files skipped from review as they are similar to previous changes (4)
- content/Training/index.mdx
- content/Training/developers/04-agent-collaboration.mdx
- content/Training/developers/03-agent-memory.mdx
- content/Training/developers/index.mdx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Workers Builds: docs
content/Training/developers/05-observability-guardrails-evals.mdx
Outdated
Show resolved
Hide resolved
content/Training/developers/05-observability-guardrails-evals.mdx
Outdated
Show resolved
Hide resolved
| Cloud deployment with test data: | ||
| - Full observability | ||
| - Options for different deployment configurations | ||
| - Ability to use different keys and environment variables | ||
|
|
||
| <Callout type="info"> | ||
| Staging environment deployment is coming soon. For now, you can test locally with DevMode and deploy directly to production. | ||
| </Callout> | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Align staging description with “Coming Soon” status
The bullets describe staging capabilities as if they’re live today, but the surrounding callouts position the whole environment as “Coming Soon.” That mismatch will confuse folks planning rollouts. Please rewrite this block so it clearly signals the features are planned/not yet available.
-Cloud deployment with test data:
-- Full observability
-- Options for different deployment configurations
-- Ability to use different keys and environment variables
+Planned cloud deployment with test data (Coming Soon):
+- Full observability
+- Options for different deployment configurations
+- Ability to use different keys and environment variables📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Cloud deployment with test data: | |
| - Full observability | |
| - Options for different deployment configurations | |
| - Ability to use different keys and environment variables | |
| <Callout type="info"> | |
| Staging environment deployment is coming soon. For now, you can test locally with DevMode and deploy directly to production. | |
| </Callout> | |
| Planned cloud deployment with test data (Coming Soon): | |
| - Full observability | |
| - Options for different deployment configurations | |
| - Ability to use different keys and environment variables | |
| <Callout type="info"> | |
| Staging environment deployment is coming soon. For now, you can test locally with DevMode and deploy directly to production. | |
| </Callout> |
🤖 Prompt for AI Agents
content/Training/developers/06-deployment-environments.mdx around lines 36 to
44: the bullet list presents staging capabilities as if available while the
Callout states staging is "Coming Soon"; update the copy to clearly indicate
these features are planned rather than live by prefacing the bullets with a
"Planned for staging" or "Coming soon" label (or move bullets into the Callout)
and change verbs/tense to future/conditional (e.g., "Will provide" or "Planned:
Full observability") so readers understand these deployment options are not yet
available and only local DevMode or direct production deploys are currently
supported.
| <Callout type="info"> | ||
| **Coming Soon**: Advanced deployment options for enterprise customers with specific compliance and security requirements. | ||
| </Callout> | ||
|
|
||
| ### Private Cloud Deployments | ||
|
|
||
| **Complete infrastructure control via CLI** | ||
|
|
||
| <Callout type="info"> | ||
| **Coming Soon**: Create and manage your own Agentuity clusters with full control over infrastructure, compliance, and data sovereignty. | ||
| </Callout> | ||
|
|
||
| #### Multi-Cloud Support | ||
| Deploy Agentuity infrastructure on your preferred cloud provider with full region selection: | ||
| - **Amazon Web Services (AWS)** - All AWS regions | ||
| - **Microsoft Azure** - Global Azure regions | ||
| - **Google Cloud Platform (GCP)** - Worldwide GCP regions | ||
| - **VMware** - On-premise and private cloud deployments | ||
|
|
||
| #### Flexible Cluster Sizing | ||
| Choose the right cluster size for your workload: | ||
|
|
||
| | Size | Use Case | Typical Workload | | ||
| |------|----------|------------------| | ||
| | **Dev** | Development & testing | Individual developers, proof of concepts | | ||
| | **Small** | Team deployments | Small teams, departmental use | | ||
| | **Medium** | Production workloads | Multiple teams, moderate scale | | ||
| | **Large** | Enterprise scale | High-volume production, multiple business units | | ||
|
|
||
| #### Complete Cluster Management | ||
| Create and manage clusters through the command-line interface with full control over: | ||
|
|
||
| - **Cluster Creation**: New cluster provisioning across supported providers | ||
| - **Region Selection**: Choose optimal geographic deployment locations | ||
| - **Machine Management**: List, remove, and monitor individual cluster machines | ||
| - **Status Monitoring**: Real-time cluster health and performance visibility | ||
|
|
||
| #### Deployment Options | ||
| - **Automated Setup**: Streamlined cloud provider integration | ||
| - **Manual Setup**: Step-by-step guidance for custom configurations | ||
| - **Full Control**: Complete networking, security, and resource customization | ||
|
|
||
| #### Enterprise Benefits | ||
| - **Data Sovereignty**: Keep all data within your infrastructure boundaries | ||
| - **Compliance Control**: Meet specific regulatory and security requirements | ||
| - **Performance Optimization**: Deploy closer to your users and data sources | ||
| - **Cost Management**: Direct control over resource allocation and scaling | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep “Coming Soon” language consistent in Enterprise section
Similar to staging, this section promises full multi-cloud/cluster control today even though the header callout says “Coming Soon.” Let’s move this paragraph into future tense (or insert explicit “Planned” qualifiers) so enterprise readers don’t expect functionality that isn’t launched yet.
-Deploy Agentuity infrastructure on your preferred cloud provider with full region selection:
+Plan to deploy Agentuity infrastructure on your preferred cloud provider with full region selection (Coming Soon):
...
-Choose the right cluster size for your workload:
+You will be able to choose the right cluster size for your workload:
...
-Create and manage clusters through the command-line interface with full control over:
+Planned CLI-based cluster management will cover:
...
-- **Automated Setup**: Streamlined cloud provider integration
-- **Manual Setup**: Step-by-step guidance for custom configurations
-- **Full Control**: Complete networking, security, and resource customization
+- **Automated Setup** (planned): Streamlined cloud provider integration
+- **Manual Setup** (planned): Step-by-step guidance for custom configurations
+- **Full Control** (planned): Complete networking, security, and resource customization📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <Callout type="info"> | |
| **Coming Soon**: Advanced deployment options for enterprise customers with specific compliance and security requirements. | |
| </Callout> | |
| ### Private Cloud Deployments | |
| **Complete infrastructure control via CLI** | |
| <Callout type="info"> | |
| **Coming Soon**: Create and manage your own Agentuity clusters with full control over infrastructure, compliance, and data sovereignty. | |
| </Callout> | |
| #### Multi-Cloud Support | |
| Deploy Agentuity infrastructure on your preferred cloud provider with full region selection: | |
| - **Amazon Web Services (AWS)** - All AWS regions | |
| - **Microsoft Azure** - Global Azure regions | |
| - **Google Cloud Platform (GCP)** - Worldwide GCP regions | |
| - **VMware** - On-premise and private cloud deployments | |
| #### Flexible Cluster Sizing | |
| Choose the right cluster size for your workload: | |
| | Size | Use Case | Typical Workload | | |
| |------|----------|------------------| | |
| | **Dev** | Development & testing | Individual developers, proof of concepts | | |
| | **Small** | Team deployments | Small teams, departmental use | | |
| | **Medium** | Production workloads | Multiple teams, moderate scale | | |
| | **Large** | Enterprise scale | High-volume production, multiple business units | | |
| #### Complete Cluster Management | |
| Create and manage clusters through the command-line interface with full control over: | |
| - **Cluster Creation**: New cluster provisioning across supported providers | |
| - **Region Selection**: Choose optimal geographic deployment locations | |
| - **Machine Management**: List, remove, and monitor individual cluster machines | |
| - **Status Monitoring**: Real-time cluster health and performance visibility | |
| #### Deployment Options | |
| - **Automated Setup**: Streamlined cloud provider integration | |
| - **Manual Setup**: Step-by-step guidance for custom configurations | |
| - **Full Control**: Complete networking, security, and resource customization | |
| #### Enterprise Benefits | |
| - **Data Sovereignty**: Keep all data within your infrastructure boundaries | |
| - **Compliance Control**: Meet specific regulatory and security requirements | |
| - **Performance Optimization**: Deploy closer to your users and data sources | |
| - **Cost Management**: Direct control over resource allocation and scaling | |
| <Callout type="info"> | |
| **Coming Soon**: Advanced deployment options for enterprise customers with specific compliance and security requirements. | |
| </Callout> | |
| ### Private Cloud Deployments | |
| **Complete infrastructure control via CLI** | |
| <Callout type="info"> | |
| **Coming Soon**: Create and manage your own Agentuity clusters with full control over infrastructure, compliance, and data sovereignty. | |
| </Callout> | |
| #### Multi-Cloud Support | |
| Plan to deploy Agentuity infrastructure on your preferred cloud provider with full region selection (Coming Soon): | |
| - **Amazon Web Services (AWS)** - All AWS regions | |
| - **Microsoft Azure** - Global Azure regions | |
| - **Google Cloud Platform (GCP)** - Worldwide GCP regions | |
| - **VMware** - On-premise and private cloud deployments | |
| #### Flexible Cluster Sizing | |
| You will be able to choose the right cluster size for your workload: | |
| | Size | Use Case | Typical Workload | | |
| |------|----------|------------------| | |
| | **Dev** | Development & testing | Individual developers, proof of concepts | | |
| | **Small** | Team deployments | Small teams, departmental use | | |
| | **Medium** | Production workloads | Multiple teams, moderate scale | | |
| | **Large** | Enterprise scale | High-volume production, multiple business units | | |
| #### Complete Cluster Management | |
| Planned CLI-based cluster management will cover: | |
| - **Cluster Creation**: New cluster provisioning across supported providers | |
| - **Region Selection**: Choose optimal geographic deployment locations | |
| - **Machine Management**: List, remove, and monitor individual cluster machines | |
| - **Status Monitoring**: Real-time cluster health and performance visibility | |
| #### Deployment Options | |
| - **Automated Setup** (planned): Streamlined cloud provider integration | |
| - **Manual Setup** (planned): Step-by-step guidance for custom configurations | |
| - **Full Control** (planned): Complete networking, security, and resource customization | |
| #### Enterprise Benefits | |
| - **Data Sovereignty**: Keep all data within your infrastructure boundaries | |
| - **Compliance Control**: Meet specific regulatory and security requirements | |
| - **Performance Optimization**: Deploy closer to your users and data sources | |
| - **Cost Management**: Direct control over resource allocation and scaling |
🤖 Prompt for AI Agents
In content/Training/developers/06-deployment-environments.mdx around lines 126
to 173, the Enterprise/Private Cloud section uses present-tense phrasing that
conflicts with the "Coming Soon" callouts; update the text to consistently
indicate future availability by changing present-tense claims to future tense or
adding explicit "Planned" / "Coming Soon" qualifiers (e.g., "Will support",
"Planned: Create and manage", "Planned multi-cloud support includes"), and
ensure list items and headings are reworded to avoid implying current
availability while preserving the same features and structure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
content/Training/developers/02-anatomy-of-an-agent.mdx(1 hunks)content/Training/developers/05-observability-guardrails-evals.mdx(1 hunks)content/Training/developers/06-deployment-environments.mdx(1 hunks)content/Training/developers/07-sandbox-capstone.mdx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- content/Training/developers/07-sandbox-capstone.mdx
- content/Training/developers/06-deployment-environments.mdx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Workers Builds: docs
| # Resolve location to coordinates (geocoding step) | ||
| coordinates = await geocode_location(location_query) | ||
| if not coordinates: | ||
| return response.json({"error": "Unable to find location coordinates"}) | ||
| # Fetch fresh data and cache with shorter TTL | ||
| weather = await fetch_nws_weather(coordinates["lat"], coordinates["lon"], location_query, context) | ||
| await context.kv.set("weather", cache_key, weather, {"ttl": 300}) # 5 minutes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Define geocode_location so the sample runs.
The manual-trigger flow now calls geocode_location, but the module never introduces that helper. Anyone copy/pasting this “key pattern” hits a NameError. Please add (or link to) a minimal geocoding helper so the snippet is runnable, or show the relevant import.
🤖 Prompt for AI Agents
In content/Training/developers/02-anatomy-of-an-agent.mdx around lines 734 to
741, the snippet calls geocode_location but that helper is not defined or
imported, causing a NameError; add a minimal geocode_location helper (or show an
import) before this snippet that accepts a location_query string and returns a
dict with "lat" and "lon" or None on failure, using a simple lookup or a call to
an external geocoding service, and update the sample to either import it from a
utilities module or include the helper inline so the example runs as-is.
| const coordinates = await geocodeLocation(locationQuery); | ||
| if (!coordinates) { | ||
| return response.json({ error: 'Unable to find location coordinates' }); | ||
| } | ||
| // Fetch fresh data and cache with shorter TTL | ||
| const weather = await fetchNWSWeather(coordinates.lat, coordinates.lon, locationQuery, context); | ||
| await context.kv.set('weather', cacheKey, weather, { ttl: 300 }); // 5 minutes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mirror the geocodeLocation helper in the TS example.
Same gap as the Python sample: geocodeLocation is invoked without ever being defined, so this example throws at runtime. Please add the helper (or reference where it lives) to keep the walkthrough executable.
🤖 Prompt for AI Agents
In content/Training/developers/02-anatomy-of-an-agent.mdx around lines 765 to
772, the example calls geocodeLocation but that helper is not defined causing a
runtime error; add a geocodeLocation helper (or an import pointing to the
existing helper) that accepts the locationQuery and returns { lat, lon } or null
on failure, ensure it handles errors and rejects gracefully, and update the
example to either import the helper or include its small implementation so the
walkthrough runs end-to-end.
| const { query } = await request.data.json(); | ||
| // Domain-specific validation rules | ||
| const inappropriateRequests = ['hack', 'illegal', 'private information']; | ||
| for (const term of inappropriateRequests) { | ||
| if (query.toLowerCase().includes(term)) { | ||
| return response.json({ | ||
| error: 'Cannot assist with inappropriate requests', | ||
| reason: \`Request contains prohibited content: '\${term}'\` | ||
| }); | ||
| } | ||
| } | ||
| // Length validation | ||
| if (query.length > 1000) { | ||
| return response.json({ | ||
| error: 'Query too long', | ||
| maxLength: 1000 | ||
| }); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handle missing query in JS guardrails example.
If query is absent from the request payload, query.toLowerCase() throws a TypeError. Mirror the Python sample by providing a safe default before you apply string operations.
- const { query } = await request.data.json();
+ const { query = '' } = await request.data.json();📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const { query } = await request.data.json(); | |
| // Domain-specific validation rules | |
| const inappropriateRequests = ['hack', 'illegal', 'private information']; | |
| for (const term of inappropriateRequests) { | |
| if (query.toLowerCase().includes(term)) { | |
| return response.json({ | |
| error: 'Cannot assist with inappropriate requests', | |
| reason: \`Request contains prohibited content: '\${term}'\` | |
| }); | |
| } | |
| } | |
| // Length validation | |
| if (query.length > 1000) { | |
| return response.json({ | |
| error: 'Query too long', | |
| maxLength: 1000 | |
| }); | |
| } | |
| const { query = '' } = await request.data.json(); | |
| // Domain-specific validation rules | |
| const inappropriateRequests = ['hack', 'illegal', 'private information']; | |
| for (const term of inappropriateRequests) { | |
| if (query.toLowerCase().includes(term)) { | |
| return response.json({ | |
| error: 'Cannot assist with inappropriate requests', | |
| reason: `Request contains prohibited content: '${term}'` | |
| }); | |
| } | |
| } | |
| // Length validation | |
| if (query.length > 1000) { | |
| return response.json({ | |
| error: 'Query too long', | |
| maxLength: 1000 | |
| }); | |
| } |
🤖 Prompt for AI Agents
In content/Training/developers/05-observability-guardrails-evals.mdx around
lines 751 to 770, the code calls query.toLowerCase() without ensuring query
exists or is a string; set a safe default and normalize the type before any
string operations (e.g. obtain the payload, default missing query to an empty
string or coerce to String, then use that normalized query variable for the
prohibited-term checks and length validation).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
app/api/tutorials/[id]/steps/[stepNumber]/route.ts (1)
45-51: Handle optional totalSteps in API response.Since
totalStepsis now optional inTutorialMetadataSchema(lib/tutorial/schemas.ts line 7), bothtotalSteps: parsed.metadata.totalSteps(line 45) and withintutorialStep(line 51) may returnundefined, potentially breaking API consumers expecting a number.Apply a fallback such as:
return NextResponse.json({ success: true, data: { tutorialId: id, - totalSteps: parsed.metadata.totalSteps, + totalSteps: parsed.metadata.totalSteps ?? parsed.steps.length, currentStep: stepNum, tutorialStep: { title: step.title, mdx: step.mdxContent, snippets: step.snippets, - totalSteps: parsed.metadata.totalSteps, + totalSteps: parsed.metadata.totalSteps ?? parsed.steps.length, estimatedTime: step.estimatedTime, } } });
🧹 Nitpick comments (5)
lib/tutorial/index.ts (2)
9-20: Consider validating config structure and avoiding type duplication.The
TutorialMetainterface closely mirrors fields inTutorialMetadataSchema(lib/tutorial/schemas.ts), creating maintenance overhead. Additionally, the config JSON is parsed without validation, which could lead to runtime errors if the structure is malformed.Consider:
- Adding a Zod schema to validate the config JSON structure
- Exporting and reusing types from schemas.ts where possible
Example validation:
import { z } from 'zod'; const TutorialMetaSchema = z.object({ id: z.string(), title: z.string(), description: z.string(), path: z.string(), difficulty: z.string().optional(), estimatedTime: z.string().optional() }); const TutorialsConfigSchema = z.object({ tutorials: z.array(TutorialMetaSchema) }); export async function getTutorialsConfig(): Promise<TutorialsConfig> { const configPath = join(process.cwd(), 'content', 'tutorials.json'); const configContent = await readFile(configPath, 'utf-8'); const parsed = JSON.parse(configContent); return TutorialsConfigSchema.parse(parsed); }
25-29: Consider caching the tutorials config.
getTutorialsConfig()reads and parses the config file on every invocation. Since this file is unlikely to change at runtime and is called by multiple routes, caching could improve performance.Example caching approach:
let cachedConfig: TutorialsConfig | null = null; export async function getTutorialsConfig(): Promise<TutorialsConfig> { if (cachedConfig) { return cachedConfig; } const configPath = join(process.cwd(), 'content', 'tutorials.json'); const configContent = await readFile(configPath, 'utf-8'); cachedConfig = JSON.parse(configContent); return cachedConfig; }content/tutorials.json (1)
4-27: Fix inconsistent indentation.The JSON has inconsistent indentation: entries at lines 4-11 use 4 spaces while entries at lines 20-27 use 2 spaces. Standardize to either 2 or 4 spaces throughout.
app/api/tutorials/route.ts (2)
34-36: Consider more visible error handling.Failed tutorials are silently filtered out with only a
console.warn. In production, this might hide configuration or content issues. Consider:
- Tracking failed tutorial IDs in the response metadata.
- Using structured logging for better observability.
- Alerting when a certain threshold of tutorials fails to load.
9-9: Add detailed error handling for tutorials.json loading
- In lib/tutorial/index.ts within getTutorialsConfig(), wrap JSON.parse in a try-catch and rethrow a descriptive error (e.g.
Error('Invalid tutorials.json at ' + configPath + ': ' + err.message)).- In app/api/tutorials/route.ts, update the catch block to log the exact error message (including file path and parse error) instead of a generic string, and consider returning a more specific response for malformed config.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
app/api/tutorials/[id]/route.ts(2 hunks)app/api/tutorials/[id]/steps/[stepNumber]/route.ts(2 hunks)app/api/tutorials/route.ts(1 hunks)content/tutorials.json(1 hunks)lib/tutorial/index.ts(1 hunks)lib/tutorial/schemas.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
app/api/tutorials/[id]/route.ts (1)
lib/tutorial/index.ts (1)
getTutorialFilePath(34-43)
app/api/tutorials/route.ts (3)
lib/tutorial/index.ts (1)
getTutorialsConfig(25-29)lib/tutorial/schemas.ts (2)
TutorialListItem(55-55)TutorialListItemSchema(23-30)lib/tutorial/mdx-parser.ts (1)
parseTutorialMDXCached(245-258)
app/api/tutorials/[id]/steps/[stepNumber]/route.ts (3)
lib/tutorial/schemas.ts (1)
StepParamsSchema(17-20)lib/tutorial/index.ts (1)
getTutorialFilePath(34-43)lib/tutorial/mdx-parser.ts (1)
parseTutorialMDXCached(245-258)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Workers Builds: docs
🔇 Additional comments (9)
app/api/tutorials/[id]/route.ts (1)
4-4: LGTM! Clean config-driven path resolution.The use of
getTutorialFilePathcentralizes path resolution and the early 404 check (lines 25-30) improves error handling by failing fast when a tutorial isn't found in the config.Also applies to: 24-30
app/api/tutorials/[id]/steps/[stepNumber]/route.ts (1)
24-30: LGTM! Consistent config-driven approach.The early 404 check and use of
getTutorialFilePathaligns well with the refactored pattern in the related route.lib/tutorial/index.ts (1)
34-43: LGTM! Clean path resolution logic.The function correctly looks up the tutorial in the config and returns null when not found, enabling proper 404 handling in the routes.
content/tutorials.json (1)
1-61: Verified MDX file existence
All referenced MDX files exist at the specified paths.app/api/tutorials/route.ts (5)
1-5: LGTM!The imports are appropriate for the config-driven approach.
27-31: LGTM!Using
safeParsewith graceful null returns is the right approach for filtering out invalid entries.
41-44: LGTM!The filtering logic correctly removes failed tutorials and returns a clean list.
45-51: LGTM!Error handling provides appropriate logging and a 500 response without exposing sensitive details.
21-21: No changes needed for totalSteps fallback logicFallback ensures
totalStepsis always anumber, satisfying the schema requirement.
| title: z.string().min(1, 'Title is required'), | ||
| description: z.string().min(1, 'Description is required'), | ||
| totalSteps: z.number().positive('Total steps must be a positive number'), | ||
| totalSteps: z.number().positive('Total steps must be a positive number').optional(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
🧩 Analysis chain
Verify totalSteps handling across schema and consuming code.
Making totalSteps optional in TutorialMetadataSchema creates an inconsistency with TutorialListItemSchema (line 27), which still requires totalSteps as non-optional. Additionally, app/api/tutorials/[id]/steps/[stepNumber]/route.ts (lines 45, 51) directly accesses parsed.metadata.totalSteps without null checks, which may now return undefined.
Consider one of these approaches:
- Make
totalStepsoptional inTutorialListItemSchemaas well, or - Provide fallback logic when constructing responses that use
totalSteps
Run the following script to check all usages of totalSteps in the codebase:
🏁 Script executed:
#!/bin/bash
# Description: Find all references to totalSteps to verify handling of optional values
# Search for totalSteps usage in TypeScript files
rg -nP --type=ts 'totalSteps' -C3Length of output: 16588
Unify totalSteps optionality and add fallback handling
- lib/tutorial/schemas.ts: TutorialMetadataSchema makes
totalStepsoptional (line 7), but TutorialListItemSchema (line 27) still requires it → schema mismatch. - app/api/tutorials/[id]/steps/[stepNumber]/route.ts (lines 45, 51) and other API/agent code directly use
parsed.metadata.totalStepswithout fallback → may beundefined. - app/chat/types.ts and ChatMessage.tsx assume
totalStepsis always defined, leading to “Step x of undefined” in the UI.
Either enforce totalSteps as required in TutorialMetadataSchema or propagate optionality through all downstream schemas/validation, and add a default (e.g. parsed.steps.length) or null checks at every consumption site.
🤖 Prompt for AI Agents
lib/tutorial/schemas.ts around line 7: TutorialMetadataSchema currently marks
totalSteps optional but other schemas and UI assume it's present, causing
mismatches and runtime "Step x of undefined". Fix this by making totalSteps
required on TutorialMetadataSchema to match TutorialListItemSchema, and then
update all consumers to defensively read totalSteps with a fallback (use
parsed.metadata.totalSteps ?? parsed.steps.length) where parsed.steps is
available; alternatively, if you choose to keep it optional, propagate
optionality to TutorialListItemSchema and every validation/usage site and add
the same fallback or null-checks before rendering.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
agent-docs/.env.example (1)
1-4: Consider aligning with dotenv-linter expectations.Adding a trailing blank line and sorting the keys (AGENTUITY_SDK_KEY first) will keep
dotenv-linterhappy and avoid churn later.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
agent-docs/.env.example(1 hunks)
🧰 Additional context used
🪛 dotenv-linter (3.3.0)
agent-docs/.env.example
[warning] 4-4: [EndingBlankLine] No blank line at the end of the file
(EndingBlankLine)
[warning] 4-4: [UnorderedKey] The AGENTUITY_SDK_KEY key should go before the TUTORIAL_API_URL key
(UnorderedKey)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Workers Builds: docs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
♻️ Duplicate comments (1)
app/api/tutorials/route.ts (1)
8-46: LGTM! Config-driven approach with secure path resolution.The migration to
getTutorialsConfig()andgetTutorialFilePath()addresses the previous path traversal concern by centralizing secure path validation and resolution. Tutorials that fail to resolve returnnulland are filtered out (line 45), ensuring only valid entries are returned.Note: The previous review comment about path traversal risk is now resolved by the use of
getTutorialFilePath()which performs secure path validation viaresolveSecurePath.
🧹 Nitpick comments (1)
lib/utils/secure-path.ts (1)
126-131: Consider validating that from <= to for line ranges.The function doesn't validate that
from <= to. Iffrom > to, the slice returns an empty string, which may be unexpected behavior. While not strictly incorrect, explicit validation would make the API more predictable.Apply this diff if you want explicit validation:
// Extract line range const lines = fileContent.split(/\r?\n/); + if (from !== undefined && to !== undefined && from > to) { + throw new Error(`Invalid line range: from (${from}) is greater than to (${to})`); + } const startIdx = Math.max(0, (from ? from - 1 : 0)); const endIdx = Math.min(lines.length, to ? to : lines.length);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
app/api/page-content/route.ts(2 hunks)app/api/tutorials/route.ts(1 hunks)components/CodeFromFiles.tsx(3 hunks)lib/tutorial/index.ts(1 hunks)lib/tutorial/mdx-parser.ts(2 hunks)lib/utils/secure-path.ts(1 hunks)lib/validation/middleware.ts(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (7)
app/api/page-content/route.ts (1)
lib/utils/secure-path.ts (1)
validatePathString(38-54)
app/api/tutorials/route.ts (3)
lib/tutorial/index.ts (2)
getTutorialsConfig(26-30)getTutorialFilePath(36-57)lib/tutorial/schemas.ts (2)
TutorialListItem(55-55)TutorialListItemSchema(23-30)lib/tutorial/mdx-parser.ts (1)
parseTutorialMDXCached(235-248)
components/CodeFromFiles.tsx (1)
lib/utils/secure-path.ts (1)
readSecureFile(109-132)
lib/validation/middleware.ts (1)
lib/utils/secure-path.ts (1)
PathIdentifierSchema(162-167)
lib/tutorial/mdx-parser.ts (1)
lib/utils/secure-path.ts (1)
readSecureFile(109-132)
lib/utils/secure-path.ts (1)
scripts/generate-docs-json.js (2)
path(4-4)fileContent(28-28)
lib/tutorial/index.ts (1)
lib/utils/secure-path.ts (1)
resolveSecurePath(65-97)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Workers Builds: docs
🔇 Additional comments (4)
lib/validation/middleware.ts (1)
4-4: LGTM! Validation logic successfully centralized.The aliasing of
TutorialIdSchematoPathIdentifierSchemamaintains backward compatibility while delegating to the centralized secure path utilities. The validation behavior remains equivalent (non-empty string without path traversal characters).Also applies to: 105-105
lib/tutorial/mdx-parser.ts (1)
9-9: LGTM! Secure file reading centralized.The replacement of manual path resolution with
readSecureFileimproves security and reduces code duplication. TherequireLeadingSlash: trueoption appropriately enforces repo-relative snippet paths, and error handling is preserved.Also applies to: 221-225
app/api/page-content/route.ts (1)
22-31: Path validation improved with centralized utilities.The two-stage validation (security checks via
validatePathString, then API-specific leading slash rejection) correctly secures the endpoint. The explicit separation between general security validation and API-specific constraints is clear and maintainable.components/CodeFromFiles.tsx (1)
48-64: LGTM! Secure file reading with proper error handling.The migration to
readSecureFilecentralizes security checks and line-range extraction. TherequireLeadingSlash: trueoption correctly enforces repo-relative paths as documented in the interface comment (line 8). Error handling gracefully returns a descriptive comment on failure.
| export async function getTutorialsConfig(): Promise<TutorialsConfig> { | ||
| const configPath = join(process.cwd(), 'content', 'tutorials.json'); | ||
| const configContent = await readFile(configPath, 'utf-8'); | ||
| return JSON.parse(configContent); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Validate JSON structure with a Zod schema.
JSON.parse on line 29 returns unvalidated data. If tutorials.json is malformed or has unexpected structure, this could cause runtime errors downstream when accessing config.tutorials.find() or other properties.
Apply this diff to add schema validation:
+const TutorialsConfigSchema = z.object({
+ tutorials: z.array(z.object({
+ id: z.string(),
+ title: z.string(),
+ description: z.string(),
+ path: z.string(),
+ difficulty: z.string().optional(),
+ estimatedTime: z.string().optional()
+ }))
+});
+
export async function getTutorialsConfig(): Promise<TutorialsConfig> {
const configPath = join(process.cwd(), 'content', 'tutorials.json');
const configContent = await readFile(configPath, 'utf-8');
- return JSON.parse(configContent);
+ const parsed = JSON.parse(configContent);
+ return TutorialsConfigSchema.parse(parsed);
}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In lib/tutorial/index.ts around lines 26 to 30, the function reads and
JSON.parse's tutorials.json without validation; replace that with a Zod-based
validation flow: import Zod, define a TutorialsConfig schema (e.g., an object
with a tutorials array and whatever fields each tutorial requires), parse the
file content, pass the parsed value to schema.parse (or safeParse) and either
return the validated result or throw/handle a descriptive error if validation
fails; ensure the function's return type stays TutorialsConfig and surface
validation errors with context (file path) so callers don't receive unvalidated
shapes.
| // Ensure the path is secure and doesn't escape the content directory | ||
| const contentDir = join(process.cwd(), 'content'); | ||
| const tutorialPath = `/${tutorial.path}`; | ||
|
|
||
| try { | ||
| return resolveSecurePath(tutorialPath, { | ||
| baseDir: contentDir, | ||
| requireLeadingSlash: true | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prevent double-slash if tutorial.path already starts with '/'.
Line 46 unconditionally prepends '/' to tutorial.path, which creates '//' if the path already starts with '/'. While resolveSecurePath may normalize this, it's cleaner to handle it explicitly.
Apply this diff:
// Ensure the path is secure and doesn't escape the content directory
const contentDir = join(process.cwd(), 'content');
- const tutorialPath = `/${tutorial.path}`;
+ const tutorialPath = tutorial.path.startsWith('/') ? tutorial.path : `/${tutorial.path}`;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Ensure the path is secure and doesn't escape the content directory | |
| const contentDir = join(process.cwd(), 'content'); | |
| const tutorialPath = `/${tutorial.path}`; | |
| try { | |
| return resolveSecurePath(tutorialPath, { | |
| baseDir: contentDir, | |
| requireLeadingSlash: true | |
| }); | |
| // Ensure the path is secure and doesn't escape the content directory | |
| const contentDir = join(process.cwd(), 'content'); | |
| const tutorialPath = tutorial.path.startsWith('/') ? tutorial.path : `/${tutorial.path}`; | |
| try { | |
| return resolveSecurePath(tutorialPath, { | |
| baseDir: contentDir, | |
| requireLeadingSlash: true | |
| }); |
🤖 Prompt for AI Agents
In lib/tutorial/index.ts around lines 44 to 52, the code unconditionally
prepends '/' to tutorial.path which can produce a double-slash when
tutorial.path already starts with '/'; change this to normalize the input first
by stripping any leading slashes from tutorial.path (or otherwise ensure exactly
one leading slash) before constructing tutorialPath so resolveSecurePath always
receives a single-leading-slash path.
| // Security check: ensure the resolved path is within the base directory | ||
| if (!absolutePath.startsWith(baseDir)) { | ||
| throw new PathSecurityError( | ||
| `Resolved path escapes base directory: ${path.relative(baseDir, absolutePath)}` | ||
| ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Path escape check vulnerable to sibling directory bypass.
Line 90's !absolutePath.startsWith(baseDir) check is insufficient. An attacker could escape to a sibling directory:
baseDir = "/home/user/app"absolutePath = "/home/user/app-sibling"(passes the check but escapes the intended directory)
Apply this diff to fix the vulnerability:
const absolutePath = path.resolve(baseDir, pathToResolve);
// Security check: ensure the resolved path is within the base directory
- if (!absolutePath.startsWith(baseDir)) {
+ const relativePath = path.relative(baseDir, absolutePath);
+ if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {
throw new PathSecurityError(
- `Resolved path escapes base directory: ${path.relative(baseDir, absolutePath)}`
+ `Resolved path escapes base directory: ${relativePath}`
);
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Security check: ensure the resolved path is within the base directory | |
| if (!absolutePath.startsWith(baseDir)) { | |
| throw new PathSecurityError( | |
| `Resolved path escapes base directory: ${path.relative(baseDir, absolutePath)}` | |
| ); | |
| } | |
| const absolutePath = path.resolve(baseDir, pathToResolve); | |
| // Security check: ensure the resolved path is within the base directory | |
| const relativePath = path.relative(baseDir, absolutePath); | |
| if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) { | |
| throw new PathSecurityError( | |
| `Resolved path escapes base directory: ${relativePath}` | |
| ); | |
| } |
🤖 Prompt for AI Agents
In lib/utils/secure-path.ts around lines 89–94, the current check using
absolutePath.startsWith(baseDir) is vulnerable to sibling-directory bypass;
replace it with a robust check using path.relative (and ensure both paths are
resolved/normalized first). Compute const rel = path.relative(baseDir,
absolutePath); then throw PathSecurityError if rel === '' ? false :
rel.split(path.sep)[0] === '..' (or more simply if rel.startsWith('..') ||
path.isAbsolute(rel)); alternatively ensure baseDir ends with path.sep and check
absolutePath.startsWith(baseDirWithSep) to avoid prefix collisions; implement
one of these secure checks and keep paths normalized/resolved beforehand.
- Update module content to provide step-by-step guidance - Add code step files (`examples/training`) for agent to use - Set training steps to a minimum of 1 (no step 0 state) - Use `dynamic-codeblock` in docs content and agent output - Remove modules 6 and 7 from `tutorials.json` (no training steps) - Update system prompts to use `askDocsAgentTool` more often
* add get tutorial progress to the tool list * add markdown converter for callout and CodeExample * remove unused code blocks * fix infinite loading session * add session edit/removal * Enhance SessionSidebar with clickable session items and improved accessibility attributes * Add button to move to sandbox * update sessions fetch scroll * adjusting scrollbar width * adjust sessions bar component and chat message display * optimistic rename/delete session for instantaneous UX * fix total steps * remove unnecessary metadata display * Update dependencies in package.json and bun.lock for @agentuity/sdk and @biomejs/biome * fix prompt context building * fix weird streams --------- Co-authored-by: afterrburn <[email protected]>
Summary by CodeRabbit
New Features
Documentation
Improvements