Skip to content

Conversation

@parteeksingh24
Copy link
Contributor

@parteeksingh24 parteeksingh24 commented Sep 16, 2025

Summary by CodeRabbit

  • New Features

    • Added a new "Training" section and Developer Training landing page with links to the full curriculum.
  • Documentation

    • Published Modules 1–7: Introduction, Anatomy, Memory, Collaboration, Observability/Guardrails/Evals, Deployment Environments, and Sandbox/Capstone — bilingual examples, labs, testing, and deployment guidance.
  • Improvements

    • Switched tutorials to a curated metadata-driven discovery with improved validation, secure content access, and an example env file for local setup.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 16, 2025

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

Adds 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

Cohort / File(s) Summary
Developer Training Modules
content/Training/developers/01-introduction-to-agents.mdx, content/Training/developers/02-anatomy-of-an-agent.mdx, content/Training/developers/03-agent-memory.mdx, content/Training/developers/04-agent-collaboration.mdx, content/Training/developers/05-observability-guardrails-evals.mdx, content/Training/developers/06-deployment-environments.mdx, content/Training/developers/07-sandbox-capstone.mdx
Adds seven comprehensive MDX modules covering agent fundamentals, lifecycle, memory, collaboration, observability/guardrails/evals, deployment environments, and a capstone sandbox with bilingual (Python/TS) examples, labs, diagrams, and testing/deployment guidance.
Training landing pages
content/Training/developers/index.mdx, content/Training/index.mdx
Adds Developer curriculum landing page and top-level Training page that link modules, describe tracks/prereqs, and surface CTAs.
Docs metadata & manifest
content/meta.json, content/tutorials.json
Inserts "Training" into docs pages array and adds content/tutorials.json as the tutorials manifest listing tutorial metadata (id, title, description, path, difficulty, estimatedTime).
Tutorial helpers & schemas
lib/tutorial/index.ts, lib/tutorial/schemas.ts
New tutorial utilities: getTutorialsConfig() and getTutorialFilePath() (resolves tutorial path or null); makes totalSteps optional in tutorial metadata schema.
Tutorials API routes
app/api/tutorials/route.ts, app/api/tutorials/[id]/route.ts, app/api/tutorials/[id]/steps/[stepNumber]/route.ts
Switches from filesystem enumeration to config-driven flow using new helpers; adds early 404 for missing tutorials, richer error logging/context, and preserves MDX parsing and response shapes.
Secure path & file utilities
lib/utils/secure-path.ts
New secure-path module: PathSecurityError, validatePathString, resolveSecurePath, readSecureFile, and Zod schemas (SecurePathStringSchema, RepoRelativePathSchema, PathIdentifierSchema) to validate and safely read repo-relative files and optional line ranges.
MDX parsing & file-read refactors
lib/tutorial/mdx-parser.ts, components/CodeFromFiles.tsx
Replace manual path joins and ad-hoc file reads with readSecureFile; remove prior repo-root checks and manual slicing; preserve error comment behavior when reads fail.
Path validation and middleware
app/api/page-content/route.ts, lib/validation/middleware.ts
Use validatePathString for explicit path validation and leading-slash guard in page-content route; middleware imports PathIdentifierSchema and aliases TutorialIdSchema to it.
Docs env example
agent-docs/.env.example
Adds example env with TUTORIAL_API_URL, VECTOR_STORE_NAME, and AGENTUITY_SDK_KEY placeholders.
API route small behavior
app/api/tutorials/[id]/route.ts, app/api/tutorials/[id]/steps/[stepNumber]/route.ts
Add early null check when getTutorialFilePath() returns falsy, returning 404 before MDX parsing.

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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

I hop through docs with whiskers keen,
Seven modules bloom where none had been.
Secure paths kept snug and tight,
Tutorials chime from morning to night.
Labs, diagrams, and code to chew — happy hacking from this rabbit to you. 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.45% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title Check ❓ Inconclusive The title “Training docs” loosely indicates that documentation is being added but is overly generic and does not specify the scope, audience, or main content of the changes. It fails to convey that the PR introduces a structured developer training curriculum with multiple modules on AI agents. Such vagueness may hinder quick understanding of the PR’s purpose in a glance at the repository history. Please revise the title to clearly reflect the scope and audience of the changes, for example “Add Developer Training Modules for AI Agents” or “Introduce AI Agents Developer Training Curriculum,” so reviewers and future maintainers can immediately grasp the primary update.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai bot requested a review from jhaynie September 16, 2025 14:44
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Sep 16, 2025

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
docs edea5c7 Oct 19 2025, 06:57 PM

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 datetime
content/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 datetime in each affected block.

+from datetime import datetime

Also 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 zlib at 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 whether similarity is a named arg on vector.search or 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 json

And in JS:

+// assume analysisResults and userId are defined above

Also applies to: 236-253


740-779: Cleanup agent: undefined helpers and imports.

get_old_sessions, timedelta, and json are 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.set and vector.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 use handoff.

Also applies to: 351-378


596-641: Summarizer: add datetime import and handle non-array content defensively.

+from datetime import datetime

And 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_validator but 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, ValidationError

Also applies to: 97-117


261-274: Cross-module API naming and invocation style.

  • Python uses context.get_agent(...); other modules use context.getAgent(...). Pick one SDK surface across docs.
  • Replace await agent.run(request) with response.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 .list contract 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

📥 Commits

Reviewing files that changed from the base of the PR and between 09d4781 and e13f57a.

📒 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-check

Files 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 reference

File: 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.

Comment on lines 118 to 121
history = await context.kv.get("conversations", session_id)
messages = history.data.json() if history.exists else []
# Analyze customer intent
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

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.

Suggested change
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.

Comment on lines +18 to +21
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)
Copy link
Member

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)

Comment on lines 145 to 147
- **AWS** launched Bedrock AgentCore (still in preview)
- **Google** released their Agent Development Kit (ADK)
- **Microsoft** is retrofitting Azure with agent capabilities
Copy link
Member

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.
Copy link
Member

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
Copy link
Member

Choose a reason for hiding this comment

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

Vercel AI SDK

Comment on lines 172 to 178
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
Copy link
Member

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.

Comment on lines 79 to 82
# 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'})
Copy link
Member

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) {
Copy link
Member

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
Copy link
Member

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.

Comment on lines 8 to 16
## 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?
Copy link
Member

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**
Copy link
Member

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?

@coderabbitai coderabbitai bot requested a review from rblalock September 24, 2025 20:14
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

📥 Commits

Reviewing files that changed from the base of the PR and between e13f57a and e209008.

📒 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

Comment on lines 36 to 44
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>

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

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.

Suggested change
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.

Comment on lines +126 to +173
<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

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

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.

Suggested change
<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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

📥 Commits

Reviewing files that changed from the base of the PR and between e209008 and 7500eda.

📒 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

Comment on lines 734 to 741
# 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
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

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.

Comment on lines 765 to 772
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
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

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.

Comment on lines 751 to 770
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
});
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

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.

Suggested change
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).

@coderabbitai coderabbitai bot requested a review from mcongrove October 1, 2025 13:25
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 totalSteps is now optional in TutorialMetadataSchema (lib/tutorial/schemas.ts line 7), both totalSteps: parsed.metadata.totalSteps (line 45) and within tutorialStep (line 51) may return undefined, 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 TutorialMeta interface closely mirrors fields in TutorialMetadataSchema (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:

  1. Adding a Zod schema to validate the config JSON structure
  2. 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:

  1. Tracking failed tutorial IDs in the response metadata.
  2. Using structured logging for better observability.
  3. 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

📥 Commits

Reviewing files that changed from the base of the PR and between 7500eda and 4a8cf87.

📒 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 getTutorialFilePath centralizes 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 getTutorialFilePath aligns 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 safeParse with 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 logic

Fallback ensures totalSteps is always a number, 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(),
Copy link
Contributor

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:

  1. Make totalSteps optional in TutorialListItemSchema as well, or
  2. 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' -C3

Length of output: 16588


Unify totalSteps optionality and add fallback handling

  • lib/tutorial/schemas.ts: TutorialMetadataSchema makes totalSteps optional (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.totalSteps without fallback → may be undefined.
  • app/chat/types.ts and ChatMessage.tsx assume totalSteps is 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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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-linter happy and avoid churn later.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4a8cf87 and cf514cb.

📒 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

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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() and getTutorialFilePath() addresses the previous path traversal concern by centralizing secure path validation and resolution. Tutorials that fail to resolve return null and 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 via resolveSecurePath.

🧹 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. If from > 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

📥 Commits

Reviewing files that changed from the base of the PR and between cf514cb and 480fee8.

📒 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 TutorialIdSchema to PathIdentifierSchema maintains 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 readSecureFile improves security and reduces code duplication. The requireLeadingSlash: true option 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 readSecureFile centralizes security checks and line-range extraction. The requireLeadingSlash: true option correctly enforces repo-relative paths as documented in the interface comment (line 8). Error handling gracefully returns a descriptive comment on failure.

Comment on lines +26 to +30
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);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

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.

Comment on lines +44 to +52
// 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
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

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.

Suggested change
// 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.

Comment on lines +89 to +94
// 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)}`
);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

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.

Suggested change
// 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.

@parteeksingh24 parteeksingh24 marked this pull request as draft October 13, 2025 15:51
parteeksingh24 and others added 2 commits October 13, 2025 11:35
- 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]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants