Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f1415d8
feat(agents): add managed-runtime mode with Claude Platform integration
djabarovgeorge May 10, 2026
3fd2dc1
fix(agents): propagate AGENT_RUNTIME channel type across dashboard lo…
djabarovgeorge May 10, 2026
105936d
feat(agents): enhance agent creation with runtime and skills support
djabarovgeorge May 11, 2026
5b7daee
fix(agents): resolve issues with agent runtime configuration and dash…
djabarovgeorge May 11, 2026
1f9fa26
feat(agents): implement adoption of existing managed agents
djabarovgeorge May 11, 2026
953ae5b
feat(agents): enhance agent provisioning with apiKey support
djabarovgeorge May 11, 2026
7c38fe8
feat(agents): enhance agent deletion process with provider option
djabarovgeorge May 11, 2026
489d540
feat(agents): add skills support to agent runtime configuration
djabarovgeorge May 11, 2026
1dfea32
feat(agents): add creationSource field to agent DTOs and commands
djabarovgeorge May 11, 2026
3ee1d69
refactor(agents): remove runtime providers endpoint and related DTOs
djabarovgeorge May 11, 2026
4b863c8
feat(agents): enhance agent runtime configuration with skills and cap…
djabarovgeorge May 11, 2026
ea6786b
feat(agents): add externalEnvironmentId to integration schema and enh…
djabarovgeorge May 11, 2026
25168f9
Merge remote-tracking branch 'origin/next' into cursor/managed-agents…
djabarovgeorge May 11, 2026
8c502f8
fix(agents): address PR review comments
djabarovgeorge May 11, 2026
a102ad1
feat(dependencies): add @anthropic-ai/sdk and standardwebhooks to pnp…
djabarovgeorge May 11, 2026
a0a5488
Merge branch 'next' into cursor/managed-agents-claude-platform
LetItRock May 12, 2026
134c793
feat(agents): refactor managed runtime integration handling
djabarovgeorge May 12, 2026
8b6d628
Merge branch 'cursor/managed-agents-claude-platform' of https://githu…
djabarovgeorge May 12, 2026
6d12930
feat(integrations): introduce integration kind distinction and update…
djabarovgeorge May 12, 2026
40980db
feat(agents): enhance managed agent provisioning and runtime configur…
djabarovgeorge May 12, 2026
8796d4e
feat(agents): update agent creation DTO and use case validation
djabarovgeorge May 12, 2026
276e794
refactor(workflow): replace NotificationChannelTypeEnum with ChannelT…
djabarovgeorge May 12, 2026
18d9a90
refactor(tests): update managed agent E2E tests to stub AgentRuntimeF…
djabarovgeorge May 12, 2026
7ddbc16
fix(tests): update managed agent E2E test to correct MCP server URL
djabarovgeorge May 12, 2026
f1186b8
chore: update hash
djabarovgeorge May 12, 2026
b8c3968
Merge branch 'next' into cursor/managed-agents-claude-platform
djabarovgeorge May 12, 2026
29b5c99
fix(api-service): enforce MCP catalog on agent runtime config PATCH (…
djabarovgeorge May 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix(agents): address PR review comments
- Remove unused ChannelTypeEnum import from preview.usecase.ts
- Enrich PATCH agent-runtime-config response with capabilities to match GET
- Fail loudly in create-agent when adopt mode returns no agent name
- Add guard in create-agent.usecase.ts: throw UnprocessableEntityException when runtime=managed but managedRuntime absent
- Fix @type decorator in create-agent.command.ts to use ManagedRuntimeDto class for proper nested validation
- Replace misleading NotFoundException with UnprocessableEntityException for missing apiKey in provision-managed-agent
- Reject unknown MCP server IDs with BadRequestException instead of substituting empty URL
- Fix update-agent-runtime-config to guard missing apiKey with UnprocessableEntityException instead of non-null assertion
- Use public @novu/application-generic entry in e2e test instead of deep build path

Co-authored-by: Cursor <[email protected]>
  • Loading branch information
djabarovgeorge and cursoragent committed May 11, 2026
commit 8c502f8f868eee9ffe1e6090911f29b8787ef397
2 changes: 1 addition & 1 deletion apps/api/src/app/agents/e2e/managed-agent.e2e.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import * as AgentRuntimeFactoryModule from '@novu/application-generic';
import {
AgentRuntimeBadRequestError,
AgentRuntimeNotFoundError,
AgentRuntimeRateLimitedError,
AgentRuntimeUnauthorizedError,
encryptCredentials,
} from '@novu/application-generic';
Comment thread
github-code-quality[bot] marked this conversation as resolved.
Fixed
import * as AgentRuntimeFactoryModule from '@novu/application-generic/build/main/agent-runtimes/agent-runtime.factory';
import { AgentRepository, IntegrationRepository } from '@novu/dal';
import { AgentRuntimeProviderIdEnum, ChannelTypeEnum } from '@novu/shared';
import { UserSession } from '@novu/testing';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
} from 'class-validator';

import { EnvironmentWithUserCommand } from '../../../shared/commands/project.command';
import type { ManagedRuntimeDto } from '../../dtos/agent-runtime-config.dto';
import { ManagedRuntimeDto } from '../../dtos/agent-runtime-config.dto';

export class CreateAgentCommand extends EnvironmentWithUserCommand {
@ValidateIf((o) => !o.managedRuntime?.externalAgentId)
Expand Down Expand Up @@ -41,7 +41,7 @@ export class CreateAgentCommand extends EnvironmentWithUserCommand {
@ValidateIf((o) => o.runtime === 'managed')
@IsObject()
@ValidateNested()
@Type(() => Object)
@Type(() => ManagedRuntimeDto)
managedRuntime?: ManagedRuntimeDto;
Comment thread
coderabbitai[bot] marked this conversation as resolved.

@IsOptional()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ConflictException, Injectable } from '@nestjs/common';
import { ConflictException, Injectable, UnprocessableEntityException } from '@nestjs/common';
import { AnalyticsService, shortId, slugifyOrRandom } from '@novu/application-generic';
import { AgentRepository } from '@novu/dal';
import { trackAgentCreated } from '../../agent-analytics';
Expand Down Expand Up @@ -40,7 +40,11 @@ export class CreateAgent {
}
}

const isManaged = command.runtime === 'managed' && command.managedRuntime;
if (command.runtime === 'managed' && !command.managedRuntime) {
throw new UnprocessableEntityException('managedRuntime is required when runtime is "managed".');
}

const isManaged = command.runtime === 'managed';

const agent = isManaged
? await this.agentRepository.withTransaction(async (session) => {
Expand Down Expand Up @@ -86,6 +90,12 @@ export class CreateAgent {
{ session }
);

if (isAdoptMode && !provisionResult.adoptedName) {
throw new Error(
`Provider returned no name for adopted agent "${command.managedRuntime?.externalAgentId}". Cannot resolve a unique identifier.`
);
}

if (isAdoptMode && provisionResult.adoptedName) {
Comment thread
coderabbitai[bot] marked this conversation as resolved.
// Resolve a unique identifier from the Claude agent name, following the
// same pattern used elsewhere in the platform: slugify + random short ID on collision.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common';
import { BadRequestException, Injectable, NotFoundException, UnprocessableEntityException } from '@nestjs/common';
import {
decryptCredentials,
encryptCredentials,
Expand Down Expand Up @@ -125,7 +125,9 @@ export class ProvisionManagedAgent {
const decryptedCredentials = decryptCredentials(integration.credentials);

if (!decryptedCredentials.apiKey) {
throw new NotFoundException(`Integration "${command.integrationId}" has no API key configured.`);
throw new UnprocessableEntityException(
`Integration "${command.integrationId}" has no API key configured. Please complete the integration setup.`
);
}

resolvedIntegrationId = integration._id;
Expand Down Expand Up @@ -155,7 +157,13 @@ export class ProvisionManagedAgent {
const resolvedMcpServers = command.mcpServers?.map((serverId) => {
const catalogServer = CLAUDE_MCP_SERVERS.find((s) => s.id === serverId);

return { name: catalogServer?.name ?? serverId, url: catalogServer?.url ?? '' };
if (!catalogServer) {
throw new BadRequestException(
`Unknown MCP server ID "${serverId}". Must be one of the supported catalog entries.`
);
}

return { name: catalogServer.name, url: catalogServer.url };
});

const response = await runtimeProvider.createAgent({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Injectable, NotFoundException, UnprocessableEntityException } from '@nestjs/common';
import { decryptCredentials, getAgentRuntimeProvider } from '@novu/application-generic';
import { AgentRepository, IntegrationRepository } from '@novu/dal';
import { AgentRuntimeConfigResponseDto } from '../../dtos/agent-runtime-config.dto';
import { AGENT_RUNTIME_PROVIDERS } from '@novu/shared';
import type { AgentRuntimeCapabilitiesDto, AgentRuntimeConfigResponseDto } from '../../dtos/agent-runtime-config.dto';
import { UpdateAgentRuntimeConfigCommand } from './update-agent-runtime-config.command';

@Injectable()
Expand Down Expand Up @@ -45,7 +46,14 @@ export class UpdateAgentRuntimeConfig {
}

const decryptedCredentials = decryptCredentials(integration.credentials);
const runtimeProvider = getAgentRuntimeProvider(providerId, decryptedCredentials.apiKey!);

if (!decryptedCredentials.apiKey) {
throw new UnprocessableEntityException(
`Integration for agent "${command.identifier}" has no API key configured. Please complete the integration setup.`
);
}

const runtimeProvider = getAgentRuntimeProvider(providerId, decryptedCredentials.apiKey);

const updated = await runtimeProvider.updateConfig(externalAgentId, {
model: command.model,
Expand All @@ -55,12 +63,25 @@ export class UpdateAgentRuntimeConfig {
skills: command.skills,
});

const providerEntry = AGENT_RUNTIME_PROVIDERS.find((p) => p.providerId === providerId);

const capabilities: AgentRuntimeCapabilitiesDto | undefined = providerEntry
? {
mcpServers: providerEntry.capabilities.mcpServers,
tools: providerEntry.capabilities.tools,
model: providerEntry.capabilities.model,
systemPrompt: providerEntry.capabilities.systemPrompt,
skills: providerEntry.capabilities.skills,
}
: undefined;

const result: AgentRuntimeConfigResponseDto = {
model: updated.model,
systemPrompt: updated.systemPrompt,
mcpServers: updated.mcpServers,
tools: updated.tools,
...(updated.skills !== undefined ? { skills: updated.skills } : {}),
...(capabilities !== undefined ? { capabilities } : {}),
};

return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Injectable } from '@nestjs/common';
import { EnvironmentRepository, EnvironmentVariableRepository } from '@novu/dal';
import { ContextResolved } from '@novu/framework/internal';
import {
ChannelTypeEnum,
EnvironmentSystemVariables,
NotificationChannelTypeEnum,
ResourceOriginEnum,
Expand Down
Loading