Example Agents
Technical Strategist
Self Hosting
Core Concepts
Example Agents
Licenses and Privacy
Example Agents
Technical Strategist
Design a comprehensive technical architecture and implementation strategy
This guide demonstrates how to implement the Technical Strategist agent in your Agentic Templates application.
Implementation Guide
Follow these steps to implement the Technical Strategist agent.
1. Implement the Agent UI
Start with the agent configuration in the dashboard repository. This is where you’ll define how the Technical Strategist appears and behaves in the UI.
Create Agent Configuration
First, create your Technical Strategist configuration in your dashboard project:
// src/lib/agents/techStrategist.agent.ts
import type { AgentConfig, OrderFormData, RequestTechStrategyInput } from '@/schemas';
import { agentService } from '@/services/agentService';
export const techStrategistAgent: AgentConfig = {
id: '4f9e3b9a-7d1c-5f5e-9c7d-9b2a4e3d2f0d',
name: 'Technical Strategist',
title: 'Technical Architect',
description: 'An expert in technical architecture and system design',
category: 'architecture',
imageUrl: 'https://images.unsplash.com/photo-1451187580459-43490279c0fa?w=400&q=80&auto=format',
credits: 25,
available: true,
keyDeliverables: [
'Use Cases Analysis',
'Non-Functional Requirements',
'Data Model (ERD)',
'Domain Model',
'Services Design',
'API Design',
'Deployment Strategy'
],
packageDescription: [
'One Page Technical Architecture'
],
estimatedDelivery: 'Less than 1 min',
fields: {
deliverableName: {
type: 'text',
label: 'Deliverable Name',
required: true,
placeholder: 'Enter your deliverable name'
},
useCases: {
type: 'textarea',
label: 'Use Cases',
required: true,
placeholder: 'Enter your application use cases'
},
nonFunctional: {
type: 'textarea',
label: 'Non-Functional Requirements',
required: true,
placeholder: 'Enter your non-functional requirements'
}
},
faq: [
{
question: 'What is the purpose of this agent?',
answer: 'This agent helps you design a comprehensive technical architecture for your application. It analyzes your requirements and provides detailed diagrams and specifications for implementation.'
}
],
deliverable: {
sections: [
{
id: 'useCases',
label: 'Use Cases',
type: 'list',
description: 'Key use cases and features',
order: 1
},
{
id: 'nonFunctional',
label: 'Non-Functional Requirements',
type: 'list',
description: 'Non-functional requirements and constraints',
order: 2
},
{
id: 'dataModel',
label: 'Data Model',
type: 'diagram',
description: 'Entity-Relationship Diagram',
order: 3
},
{
id: 'domainModel',
label: 'Domain Model',
type: 'diagram',
description: 'Domain class diagram',
order: 4
},
{
id: 'servicesDesign',
label: 'Services Design',
type: 'diagram',
description: 'Microservices architecture diagram',
order: 5
},
{
id: 'apiDesign',
label: 'API Design',
type: 'text',
description: 'OpenAPI specification',
order: 6
},
{
id: 'deployment',
label: 'Deployment',
type: 'text',
description: 'Deployment strategy and infrastructure',
order: 7
}
],
availableFormats: ['pdf', 'markdown'],
},
handler: async (token: string, data: OrderFormData) => {
const response = await agentService.handleTechStrategyRequest(
token,
data.payload.formData as RequestTechStrategyInput
);
return response;
}
};
Update the index file in lib/agents/index.ts
// src/lib/agents/index.ts
import { techStrategistAgent } from './techStrategist.agent';
export const agents = {
techStrategist: techStrategistAgent,
// ... other agents
} as const;
Update schemas/agent.ts
with the input types for the agent
// src/schemas/agent.ts
import { z } from 'zod';
export const TechStrategyInputSchema = z.object({
useCases: z.string(),
nonFunctional: z.string(),
deliverableName: z.string()
});
export type TechStrategyInput = z.infer<typeof TechStrategyInputSchema>;
Update schemas/api.ts
with the response body expected from the API
// src/schemas/api.ts
import { z } from 'zod';
export const TechStrategyResponseSchema = z.object({
orderId: z.string(),
orderStatus: z.string(),
orderCreatedAt: z.string(),
deliverableName: z.string()
});
export type TechStrategyResponse = z.infer<typeof TechStrategyResponseSchema>;
Add the handler to services/agentService.ts
// src/services/agentService.ts
import { TechStrategyInput, TechStrategyResponse } from '@/schemas';
import { api } from './api';
export const agentService = {
handleTechStrategyRequest: async (
token: string,
input: TechStrategyInput
): Promise<TechStrategyResponse> => {
return await api.post('/tech-strategy', input, token);
}
};
2. Implement the API Endpoints
2.1 Update the infrastructure to support the Technical Strategist
Update the infra/api.ts
file
// infra/api.ts
api.route("POST /tech-strategy", {
link: [...apiResources],
handler: "./packages/functions/src/orchestrator.api.handleRequestTechStrategy",
timeout: "900 seconds"
});
Update the infra/queues.ts
file
// infra/queues.ts
export const techStrategyQueue = new sst.aws.Queue("TechStrategyQueue", {
fifo: true
});
techStrategyQueue.subscribe({
handler: "./packages/functions/src/agent-plane.api.techStrategyHandler",
link: [
deliverablesTable,
ordersTable,
openaiApiKey,
],
permissions: [
{
actions: ["dynamodb:*"],
resources: [deliverablesTable.arn, ordersTable.arn]
}
],
timeout: "10 minutes"
});
Update the infra/topic.ts
file
// infra/topic.ts
orderTopic.subscribeQueue(
"techStrategy",
techStrategyQueue.arn,
{
filter: {
"queue": ["techStrategy"]
}
}
);
2.2 Update the orchestrator to route the request to the order topic
Update the metadata/agent-plane.schema.ts
file with input types
// packages/core/src/orchestrator/metadata/agent-plane.schema.ts
import { z } from 'zod';
// Simple validator that checks for basic mermaid syntax
const validateMermaid = (value: string): boolean => {
const validDiagramTypes = [
'erDiagram',
'classDiagram',
'sequenceDiagram',
'flowchart',
'graph'
];
const firstLine = value.trim().split('\n')[0].trim();
return validDiagramTypes.some(type => firstLine.startsWith(type));
};
export const TechStrategySchema = z.object({
sections: z.object({
useCases: z.object({
id: z.string(),
label: z.string(),
type: z.literal('list'),
description: z.string().optional(),
data: z.array(z.string()),
}),
nonFunctional: z.object({
id: z.string(),
label: z.string(),
type: z.literal('list'),
description: z.string().optional(),
data: z.array(z.string()),
}),
dataModel: z.object({
id: z.string(),
label: z.string(),
type: z.literal('diagram'),
description: z.string().optional(),
data: z.string().refine(
(val) => validateMermaid(val),
{ message: "Invalid Mermaid ERD diagram" }
),
}),
domainModel: z.object({
id: z.string(),
label: z.string(),
type: z.literal('diagram'),
description: z.string().optional(),
data: z.string().refine(
(val) => validateMermaid(val),
{ message: "Invalid Mermaid class diagram" }
),
}),
servicesDesign: z.object({
id: z.string(),
label: z.string(),
type: z.literal('diagram'),
description: z.string().optional(),
data: z.string().refine(
(val) => validateMermaid(val),
{ message: "Invalid Mermaid service diagram" }
),
}),
apiDesign: z.object({
id: z.string(),
label: z.string(),
type: z.literal('text'),
description: z.string().optional(),
data: z.string(),
}),
deployment: z.object({
id: z.string(),
label: z.string(),
type: z.literal('text'),
description: z.string().optional(),
data: z.string(),
})
})
});
export const BasePayloadSchema = z.object({
userId: z.string(),
orderId: z.string(),
deliverableId: z.string(),
deliverableName: z.string(),
agentId: z.string(),
});
export const RequestTechStrategyInputSchema = BasePayloadSchema.extend({
useCases: z.string(),
nonFunctional: z.string(),
});
export type RequestTechStrategyInput = z.infer<typeof RequestTechStrategyInputSchema>;
Update the metadata/order.enum.ts
file with the cost of the agent
// packages/core/src/orchestrator/metadata/order.enum.ts
export enum AgentCost {
TechStrategy = 25,
}
2.3 Add the Technical Strategist module to the agent-plane
Create the following directory structure:
agent-plane/technical-strategist/
├── adapters/
│ ├── primary/
│ │ └── create-tech-strategy.adapter.ts
│ └── secondary/
│ ├── openai.adapter.ts
│ └── datastore.adapter.ts
├── metadata/
│ ├── technical-strategist.schema.ts
│ └── technical-strategist.prompt.ts
└── usecases/
└── create-tech-strategy.usecase.ts
Implement the metadata for the agent in metadata/technical-strategist.prompt.ts
// packages/core/src/agent-plane/technical-strategist/metadata/technical-strategist.prompt.ts
export const techStrategySystemPrompt = (input: RequestTechStrategyInput) => `
You are an expert technical architect.
Your order is to create a detailed one-page technical specification based on the provided application requirements, technical constraints, and scalability needs For the following input:
You do not need to inlcude User Authentication, Authorization, or any other security related fields.
Focus on the business logic and data model and features.
Use Event Driven Architecture and Microservices design principles.
Use Hexagonal Architecture.
Leverage AWS services and features.
Include Topics, Queues, and Event Bus as needed.
${JSON.stringify(input)}
Focus on architecture decisions and implementation recommendations.
For the dataModel field, you MUST generate a valid Mermaid.js ERD diagram.
Use this format:
erDiagram
EntityA ||--o{ EntityB : relationship
EntityA {
string id
string name
}
EntityB {
string id
string description
}
Ensure all relationships use proper Mermaid.js ERD notation: ||--o{, }|--|{, etc.
For domainModel field, you MUST generate a valid Mermaid.js class diagram.
Use this format:
classDiagram
class EntityA {
string id
string name
}
class EntityB {
string id
string description
}
For servicesDesign field, you MUST generate a valid Mermaid.js diagram that shows the high level services and their relationships
using microservices design principles.
For API Design, you MUST generate a valid OpenAPI 3.1.0 specification.
`;
Implement the primary adapter in adapters/primary/create-tech-strategy.adapter.ts
// packages/core/src/agent-plane/technical-strategist/adapters/primary/create-tech-strategy.adapter.ts
import { SQSEvent, SQSRecord } from 'aws-lambda';
import { RequestTechStrategyInputSchema } from '@agent-plane/technical-strategist/metadata/technical-architect.schema';
import { createTechStrategyUsecase } from '@agent-plane/technical-strategist/usecases/create-tech-strategy.usecase';
export const createTechStrategyAdapter = async (event: SQSEvent) => {
console.info("--- Tech Strategy Queue Adapter ---");
if (!event.Records || event.Records.length === 0) {
throw new Error("Missing SQS Records");
}
const results = await Promise.all(event.Records.map(async (record: SQSRecord) => {
const message = JSON.parse(record.body);
const order = RequestTechStrategyInputSchema.parse(JSON.parse(message.Message));
return await createTechStrategyUsecase(order);
}));
return results;
};
Implement the usecase in usecases/create-tech-strategy.usecase.ts
// packages/core/src/agent-plane/technical-strategist/usecases/create-tech-strategy.usecase.ts
import { Deliverable, DeliverableDTO, RequestTechStrategyInput } from '@agent-plane/technical-strategist/metadata/technical-architect.schema'
import { runTechStrategy } from '@agent-plane/technical-strategist/adapters/secondary/openai.adapter';
import { deliverableRepository } from '@agent-plane/technical-strategist/adapters/secondary/datastore.adapter';
import { Message } from '@utils/metadata/message.schema';
export const createTechStrategyUsecase = async (input: RequestTechStrategyInput): Promise<Message> => {
console.info("--- Creating Technical Strategy via Usecase ---");
try {
const result = await runTechStrategy(input);
const deliverable: DeliverableDTO = {
userId: input.userId,
orderId: input.orderId,
deliverableId: input.deliverableId,
deliverableName: input.deliverableName,
agentId: input.agentId,
...result
};
await deliverableRepository.saveDeliverable(deliverable);
return {
message: "Technical strategy created successfully"
};
} catch (error) {
console.error('Error generating technical strategy:', error);
throw new Error('Failed to generate technical strategy');
}
};
Implement the secondary adapter in adapters/secondary/openai.adapter.ts
// packages/core/src/agent-plane/technical-strategist/adapters/secondary/openai.adapter.ts
import OpenAI from "openai";
import { Deliverable, DeliverableSchema, RequestTechStrategyInput } from "@agent-plane/technical-strategist/metadata/technical-architect.schema";
import { Resource } from "sst";
import { withRetry } from "@utils/tools/retry";
import { techStrategySystemPrompt } from "../../metadata/technical-strategist.prompt";
import { zodToJsonSchema } from "zod-to-json-schema";
import { zodResponseFormat } from "openai/helpers/zod";
const client = new OpenAI({
apiKey: Resource.OpenAIApiKey.value
});
export const createTechStrategy = async (input: RequestTechStrategyInput): Promise<Deliverable> => {
console.info("--- Creating Technical Strategy via Agent ---");
try {
// Create an Assistant
const assistant = await client.beta.assistants.create({
name: "Technical Strategist",
instructions: techStrategySystemPrompt(input),
model: "gpt-4",
response_format: zodResponseFormat(DeliverableSchema, "deliverable"),
tools: [{ type: "function", function: {
name: "generateDeliverable",
parameters: zodToJsonSchema(DeliverableSchema)
}}]
});
// Create a Thread
const thread = await client.beta.threads.create();
// Run the Assistant and wait for completion
const run = await client.beta.threads.runs.create(thread.id, {
assistant_id: assistant.id
});
// Wait for completion with proper status handling
const completedRun = await waitForRunCompletion(client, thread.id, run.id);
// Get the messages
const messages = await client.beta.threads.messages.list(thread.id);
const lastMessage = messages.data[0];
if (!lastMessage.content || lastMessage.content.length === 0) {
throw new Error("No content generated");
}
const textContent = lastMessage.content.find(c => c.type === 'text');
if (!textContent) {
throw new Error("No text content found");
}
const content = JSON.parse(textContent.text.value);
const validatedContent = await DeliverableSchema.parseAsync(content);
// Cleanup
await client.beta.assistants.del(assistant.id);
await client.beta.threads.del(thread.id);
return validatedContent;
} catch (error) {
console.error('Error generating technical strategy:', error);
throw error;
}
};
async function waitForRunCompletion(client: OpenAI, threadId: string, runId: string) {
while (true) {
const run = await client.beta.threads.runs.retrieve(threadId, runId);
switch (run.status) {
case 'completed':
return run;
case 'failed':
case 'cancelled':
case 'expired':
throw new Error(`Run ended with status: ${run.status}`);
case 'requires_action':
if (run.required_action?.type === 'submit_tool_outputs') {
const toolCall = run.required_action.submit_tool_outputs.tool_calls[0];
const functionArgs = JSON.parse(toolCall.function.arguments);
await client.beta.threads.runs.submitToolOutputs(threadId, runId, {
tool_outputs: [{
tool_call_id: toolCall.id,
output: JSON.stringify(functionArgs)
}]
});
}
break;
default:
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
}
export const runTechStrategy = withRetry(createTechStrategy, {
retries: 3,
delay: 1000,
onRetry: (error: Error) => console.warn('Retrying tech strategy generation due to error:', error)
});
This completes the implementation of the Technical Strategist agent. The agent will now:
- Accept user input through the UI (use cases and non-functional requirements)
- Validate and process the request through the API
- Generate a comprehensive technical architecture using OpenAI
- Store the deliverable in the database
- Return the result to the user
Remember to:
- Test each component thoroughly
- Handle errors appropriately
- Follow the AMU pattern for clean architecture
- Use proper typing and validation
- Document your code
- Add appropriate logging
- Follow security best practices
Was this page helpful?
On this page
- Implementation Guide
- 1. Implement the Agent UI
- Create Agent Configuration
- Update the index file in lib/agents/index.ts
- Update schemas/agent.ts with the input types for the agent
- Update schemas/api.ts with the response body expected from the API
- Add the handler to services/agentService.ts
- 2. Implement the API Endpoints
- 2.1 Update the infrastructure to support the Technical Strategist
- Update the infra/api.ts file
- Update the infra/queues.ts file
- Update the infra/topic.ts file
- 2.2 Update the orchestrator to route the request to the order topic
- Update the metadata/agent-plane.schema.ts file with input types
- Update the metadata/order.enum.ts file with the cost of the agent
- 2.3 Add the Technical Strategist module to the agent-plane
- Implement the metadata for the agent in metadata/technical-strategist.prompt.ts
- Implement the primary adapter in adapters/primary/create-tech-strategy.adapter.ts
- Implement the usecase in usecases/create-tech-strategy.usecase.ts
- Implement the secondary adapter in adapters/secondary/openai.adapter.ts