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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .github/workflows/01-create-release-branch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 24

- name: Set up Python
uses: actions/setup-python@v5
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/11-check-code-styling.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 24
cache: 'pnpm'
cache-dependency-path: web/pnpm-lock.yaml

Expand All @@ -85,7 +85,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 24
cache: 'pnpm'
cache-dependency-path: web/pnpm-lock.yaml

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/33-update-api-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 24

- name: Download latest OpenAPI spec
run: curl -sSf "https://cloud.agenta.ai/api/openapi.json" -o docs/docs/reference/openapi.json
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/44-railway-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ jobs:
if: steps.auth_bootstrap.outputs.enabled == 'true'
uses: actions/setup-node@v4
with:
node-version: "20"
node-version: "24"

- name: Install pnpm
if: steps.auth_bootstrap.outputs.enabled == 'true'
Expand Down Expand Up @@ -647,7 +647,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
node-version: "24"

- name: Install pnpm
uses: pnpm/action-setup@v4
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
**/*.vscode
**/*.pem
**/*dont_commit_me*
web/packages/agenta-api-client/dist/

__pycache__/
**/__pycache__/
Expand Down Expand Up @@ -68,6 +69,7 @@ services/ee/tests/results/
!api/.dockerignore
!services/.dockerignore
!.env.example
!web/.prettierignore

# Temporary SDK copies created by run.sh --local
api/sdks
Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- If you make changes to the frontend, make sure to run `pnpm lint-fix` within the web folder
- If you make changes to the API or SDK, make sure to run `ruff format` and `ruff check --fix` within the SDK or API folder (run from the repo root: `ruff format` then `ruff check`; fix all errors before committing)
- If you update Ant Design tokens, run `pnpm generate:tailwind-tokens` in the web folder and commit the generated file
- The Fern-generated `@agenta/api-client` ships as a compiled `dist/` (entry: `./dist/index.js`). `pnpm install` runs the package's `prepare` script which builds `dist/` automatically — so a fresh checkout works out of the box. **If you regenerate the client (`bash ./clients/scripts/generate.sh --language typescript`) or edit `web/packages/agenta-api-client/src/`, run `pnpm install` again or `pnpm --filter @agenta/api-client build` so consumers (`@agenta/sdk`, `@agenta/entities`, `web/oss`, `web/ee`) see the update. The `.js` extensions in Fern's relative imports are intentional NodeNext-style emission and resolve only via the compiled `dist/`.**

## Environment Config Conventions
- For API configuration, add new environment variables to `api/oss/src/utils/env.py` and consume them via the shared `env` object.
Expand Down
2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,6 @@
]
},
"engines": {
"node": ">=18.0"
"node": ">=24"
}
}
3,721 changes: 1,894 additions & 1,827 deletions docs/pnpm-lock.yaml

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions web/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
packages/agenta-api-client/
_reference/
18 changes: 18 additions & 0 deletions web/_reference/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Reference packages (read-only)

This directory holds v2-era TypeScript SDK packages copied from `arda/auto-agenta-poc` for design lookup while the v3 thin-wrapper SDK is being built at [`../packages/agenta-sdk/`](../packages/agenta-sdk/).

**These packages are NOT part of the pnpm workspace.** They live outside `web/packages/` so the `packages/*` glob in [`web/pnpm-workspace.yaml`](../pnpm-workspace.yaml) doesn't pick them up. Nothing builds, installs, or links them.

## Contents

| Package | Purpose in v2 | Disposition under v3 |
|---|---|---|
| `agenta-sdk` | Hand-rolled HTTP client + 22 resource classes + Zod boundary validation + retry logic + typed error hierarchy | Replaced by Fern-generated `@agenta/api-client` consumed by the new thin `@agenta/sdk` |
| `agenta-sdk-tracing` | OTel exporter wrapper, framework mappers, hierarchy repair, span filter | Mappers deleted (backend canonicalizes); hierarchy-repair survives; tracing API moves to `AgentaSpanProcessor` model |
| `agenta-sdk-ai` | Vercel AI SDK helpers — `createAgentWithPrompts`, `syncToolDefinitions`, traceID injection | Killed as standalone package; `createAgentWithPrompts` + `syncToolDefinitions` move to `@agenta/sdk/ai` sub-export |
| `agenta-sdk-mastra` | Mastra adapter (~50% of AI SDK helper surface) | Killed — Mastra emits OTel natively |

## How to use

Read the source for design context. Don't import from here. Don't add references to these paths in any package.json.
21 changes: 21 additions & 0 deletions web/_reference/agenta-sdk-ai/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "@agenta/sdk-ai",
"version": "0.1.0",
"description": "Agenta SDK — Vercel AI SDK adapter (traced responses, agent builder with prompts)",
"main": "./src/index.ts",
"types": "./src/index.ts",
"scripts": {
"typecheck": "tsc --noEmit"
},
"devDependencies": {
"@types/node": "^25.6.0"
},
"dependencies": {
"@agenta/sdk": "workspace:../agenta-sdk",
"@agenta/sdk-tracing": "workspace:../agenta-sdk-tracing"
},
"peerDependencies": {
"@opentelemetry/api": "^1",
"ai": ">=4"
}
}
167 changes: 167 additions & 0 deletions web/_reference/agenta-sdk-ai/src/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
# Agenta SDK — AI SDK Adapter

Integration layer for [Vercel AI SDK v6](https://sdk.vercel.ai). This is the ONLY module that imports from the `ai` package — the core SDK and tracing pipeline remain framework-agnostic.

## Exports

```ts
import {
createAgentaTracedResponse, // Wrap chat route with tracing
createAgentWithPrompts, // Create agent with Agenta-managed prompts
initAgentaTracing, // Re-exported from tracing (convenience)
withSpan, // Re-exported from tracing (convenience)
} from "@/lib/agenta-sdk/ai";
```

## `createAgentaTracedResponse`

The primary integration point for chat API routes. Replaces ~60 lines of manual OTel ceremony with one function call.

```ts
// app/api/chat/route.ts
import { createAgentaTracedResponse } from "@/lib/agenta-sdk/ai";

export async function POST(req: Request) {
const { messages, sessionId } = await req.json();
const agent = await createMyAgent();

return createAgentaTracedResponse({
agent,
messages,
sessionId,
applicationSlug: "my-app",
onFinish: ({ messages }) => {
// Your persistence logic — runs after span ends
},
onError: (error) => {
// Your error handling — runs after span ends
return "Something went wrong.";
},
});
}
```

### What it does automatically

1. **Auto-initializes tracing** — calls `initAgentaTracing()` lazily on first use
2. **Creates a parent span** — `chat:{sessionId}` with Agenta attributes
3. **Wraps in OTel context** — AI SDK child spans become children of the parent
4. **Injects trace ID** — `messageMetadata` callback sends `{ traceId }` to the client
5. **Manages span lifecycle** — ends span in `onFinish` (success) or `onError` (failure)
6. **Forwards callbacks** — your `onFinish`/`onError` still work, called after span ends

### Options

| Option | Type | Required | Description |
|--------|------|----------|-------------|
| `agent` | `Agent` | Yes | AI SDK agent (ToolLoopAgent or custom) |
| `messages` | `UIMessage[]` | Yes | Chat messages |
| `sessionId` | `string` | No | Groups spans + enables session queries |
| `userId` | `string` | No | Tagged on spans for filtering |
| `applicationSlug` | `string` | No | Links traces to Agenta prompt app |
| `applicationId` | `string` | No | Explicit app ID (overrides slug lookup) |
| `applicationRevisionId` | `string` | No | Explicit revision ID |
| `onFinish` | `(event) => void` | No | Called after streaming completes |
| `onError` | `(error) => string` | No | Called on error, return user-facing message |

## `createAgentWithPrompts`

Creates a `ToolLoopAgent` with instructions composed from Agenta's prompt registry, tool schemas merged from Agenta, and telemetry pre-configured.

```ts
import { createAgentWithPrompts } from "@/lib/agenta-sdk/ai";
import { stepCountIs } from "ai";

const agent = await createAgentWithPrompts({
model: getModel(),
applicationSlug: "rh-onboarding",
promptSlugs: ["rh-voice", "rh-onboarding", "rh-workflow"],
environment: "development",
tools: myLocalTools,
fallbacks: localFallbacks,
dynamicSections: {
integrations: "## Connected: Stripe, Google Sheets",
},
stopWhen: stepCountIs(15),
});
```

### What it does automatically

1. **Fetches prompts** — from the deployed environment (with caching + fallbacks)
2. **Extracts tool schemas** — from Agenta's prompt apps
3. **Merges tool schemas** — overrides local tool descriptions/parameters with Agenta-managed versions (keeps local `execute` functions)
4. **Resolves app refs** — gets `applicationId` + `revisionId` for telemetry
5. **Configures telemetry** — sets `experimental_telemetry` with all Agenta metadata
6. **Creates the agent** — returns a ready-to-use `ToolLoopAgent`

### Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `model` | `LanguageModel` | Required | LLM model |
| `promptSlugs` | `string[]` | `[]` | Prompt modules to compose, in order |
| `environment` | `string` | `"development"` | Environment to fetch from |
| `tools` | `ToolSet` | `{}` | Local tools (SDK merges Agenta schemas on top) |
| `fallbacks` | `Record<string, string>` | `{}` | Local fallback prompt content |
| `dynamicSections` | `Record<string, string>` | — | Appended after all modules |
| `templateVars` | `Record<string, string>` | — | `{{key}}` interpolation |
| `stopWhen` | `StopCondition` | — | Agent loop stop condition |
| `applicationSlug` | `string` | First promptSlug | Primary app for telemetry |
| `agenta` | `Agenta` | Auto-created | SDK client instance |
| `telemetry` | `boolean` | Auto (checks API key) | Enable/disable |
| `telemetryMetadata` | `Record<string, string>` | `{}` | Extra metadata on spans |

## Migration from Manual Setup

### Before (manual, ~100 lines across 3 files)

```ts
// lib/agent.ts
const [instructions, schemas, refs] = await Promise.all([
composeInstructions(MODULE_ORDER, getFallbacks(), { integrations }),
fetchToolSchemas(),
getApplicationRefs(),
]);
const tools = mergeAgentaSchemas(localTools, schemas);
return new ToolLoopAgent({
model, instructions, tools,
experimental_telemetry: { isEnabled: true, metadata: { applicationId: refs.applicationId } },
});

// app/api/chat/route.ts
const tracer = otelTrace.getTracer("my-app");
const span = tracer.startSpan(`chat:${sessionId}`);
const traceId = span.spanContext().traceId;
const ctx = otelTrace.setSpan(otelContext.active(), span);
return otelContext.with(ctx, () => {
return createAgentUIStreamResponse({
agent, uiMessages: messages,
messageMetadata: () => ({ traceId }),
onFinish: () => { span.end(); },
onError: () => { span.end(); },
});
});

// instrumentation.ts
initTelemetry(); // 500 lines of custom OTel setup
```

### After (SDK, ~15 lines total)

```ts
// lib/agent.ts
import { createAgentWithPrompts } from "@/lib/agenta-sdk/ai";
return createAgentWithPrompts({
model: getModel(),
promptSlugs: [...MODULE_ORDER],
tools: localTools,
fallbacks: getFallbacks(),
});

// app/api/chat/route.ts
import { createAgentaTracedResponse } from "@/lib/agenta-sdk/ai";
return createAgentaTracedResponse({ agent, messages, sessionId });

// instrumentation.ts — not needed (auto-initializes)
```
38 changes: 38 additions & 0 deletions web/_reference/agenta-sdk-ai/src/agent-context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Agenta SDK — Agent Context Store.
*
* Uses a WeakMap to attach Agenta metadata to AI SDK agent instances
* without monkey-patching properties onto them. This keeps the
* agent's type clean with no unsafe casts.
*/

import type {Agent} from "ai"

export interface AgentaContext {
applicationSlug?: string
applicationId?: string
applicationRevisionId?: string
environment?: string
}

/**
* WeakMap stores context per agent instance.
* Garbage-collected when the agent is no longer referenced.
*/
const contextStore = new WeakMap<object, AgentaContext>()

/**
* Attach Agenta context to an agent instance.
* Called by `createAgentWithPrompts` after agent creation.
*/
export function setAgentaContext(agent: Agent, ctx: AgentaContext): void {
contextStore.set(agent, ctx)
}

/**
* Read Agenta context from an agent instance.
* Called by `createAgentaTracedResponse` to infer application refs.
*/
export function getAgentaContext(agent: Agent): AgentaContext | undefined {
return contextStore.get(agent)
}
Loading
Loading