Discover and Export available Agent(s) as MCP Servers
Comprehensive guide to integrating embabel-agent-mcpserver with the Embabel Agent Framework, covering automatic agent discovery, goal exposure, and advanced integration patterns.
Embabel-agent-mcpserver seamlessly integrates with the Embabel Agent Framework to automatically expose AI agents and their goals as MCP tools, enabling Claude Desktop and other MCP clients to interact with Embabel agents without manual configuration.
┌─────────────────────────────────────────────────────────┐
│ Embabel Agent Framework │
│ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ @Agent │ │ @Agent │ │ @Agent │ │
│ │ UserAgent │ │ DataAgent │ │ PayAgent │ │
│ └──────┬─────┘ └──────┬─────┘ └──────┬─────┘ │
│ │ │ │ │
│ │ @Goal methods │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────────────────────────────────────┐ │
│ │ LlmReference Registry │ │
│ │ (Auto-discovered agents & goals) │ │
│ └──────────────────┬───────────────────────────┘ │
└─────────────────────┼───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Embabel Agent MCP Server │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ McpToolExport.fromLlmReference() │ │
│ │ - Converts agents to MCP tools │ │
│ │ - Applies naming strategies │ │
│ │ - Generates tool schemas │ │
│ └──────────────────┬───────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────┐ │
│ │ MCP Server (Sync/Async) │ │
│ │ - Exposes tools via SSE │ │
│ │ - Handles tool invocations │ │
│ └──────────────────────────────────────────────┘ │
└─────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ MCP Clients │
│ (Claude Desktop, Custom Clients) │
└─────────────────────────────────────────────────────────┘@Agent annotated classes@Goal methods automatically become MCP toolsMcpToolExport.fromLlmReference() handles conversionEmbabel agents are defined using @Agent and @Goal annotations: { .api }
import com.embabel.agent.api.common.Agent
import com.embabel.agent.api.common.Goal
@Agent
class UserManagementAgent {
@Goal(
name = "createUser",
description = "Create a new user account with the provided information"
)
fun createUser(input: CreateUserInput): CreateUserOutput {
// Agent implementation
val userId = userService.createUser(
email = input.email,
name = input.name,
role = input.role
)
return CreateUserOutput(
userId = userId,
success = true,
message = "User created successfully"
)
}
@Goal(
name = "deleteUser",
description = "Delete an existing user account by ID"
)
fun deleteUser(input: DeleteUserInput): DeleteUserOutput {
userService.deleteUser(input.userId)
return DeleteUserOutput(
success = true,
message = "User deleted successfully"
)
}
@Goal(
name = "updateUserRole",
description = "Update the role of an existing user"
)
fun updateUserRole(input: UpdateRoleInput): UpdateRoleOutput {
userService.updateRole(input.userId, input.newRole)
return UpdateRoleOutput(
userId = input.userId,
newRole = input.newRole,
success = true
)
}
}
// Input/Output types
data class CreateUserInput(
val email: String,
val name: String,
val role: String = "user"
)
data class CreateUserOutput(
val userId: String,
val success: Boolean,
val message: String
)
data class DeleteUserInput(val userId: String)
data class DeleteUserOutput(val success: Boolean, val message: String)
data class UpdateRoleInput(val userId: String, val newRole: String)
data class UpdateRoleOutput(val userId: String, val newRole: String, val success: Boolean)Enable Embabel agent auto-discovery: { .api }
# application.properties
# Enable Embabel agent framework
embabel.agent.enabled=true
# Package to scan for agents
embabel.agent.package-scan=com.example.agents
# Auto-discovery of agents
embabel.agent.auto-discovery=trueimport org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.context.annotation.ComponentScan
@SpringBootApplication
@ComponentScan(basePackages = [
"com.example.agents", // Your agent packages
"com.embabel.agent" // Embabel framework
])
class Application@Agent classesLlmReference for each agentLlmReference beans available for injectionAuto-Injection: { .api }
import com.embabel.agent.api.common.LlmReference
import org.springframework.stereotype.Service
@Service
class AgentRegistry(
// All discovered LlmReferences auto-injected
private val llmReferences: List<LlmReference>
) {
fun listAllAgents(): List<String> {
return llmReferences.map { it.name }
}
fun findAgent(name: String): LlmReference? {
return llmReferences.find { it.name == name }
}
fun getAgentCount(): Int {
return llmReferences.size
}
init {
println("Discovered ${llmReferences.size} agents:")
llmReferences.forEach { ref ->
println(" - ${ref.name}: ${ref.goals.size} goals")
}
}
}Publisher Integration: { .api }
import com.embabel.agent.mcpserver.McpExportToolCallbackPublisher
import com.embabel.agent.mcpserver.McpToolExport
@Service
class EmbabelAgentPublisher(
private val llmReferences: List<LlmReference>
) : McpExportToolCallbackPublisher {
override val toolCallbacks: List<ToolCallback>
get() = llmReferences.flatMap { reference ->
McpToolExport.fromLlmReference(reference).toolCallbacks
}
override fun infoString(verbose: Boolean?, indent: Int): String {
return "EmbabelAgentPublisher: ${toolCallbacks.size} tools from " +
"${llmReferences.size} agents"
}
}Filter by Agent Name: { .api }
@Service
class FilteredAgentPublisher(
private val llmReferences: List<LlmReference>
) : McpExportToolCallbackPublisher {
private val exposedAgents = setOf("UserManagementAgent", "DataAgent")
override val toolCallbacks: List<ToolCallback>
get() = llmReferences
.filter { it.name in exposedAgents }
.flatMap { reference ->
McpToolExport.fromLlmReference(reference).toolCallbacks
}
override fun infoString(verbose: Boolean?, indent: Int): String =
"FilteredAgentPublisher: ${toolCallbacks.size} tools"
}Filter by Goal Prefix: { .api }
@Service
class PublicApiPublisher(
private val llmReferences: List<LlmReference>
) : McpExportToolCallbackPublisher {
override val toolCallbacks: List<ToolCallback>
get() = llmReferences.flatMap { reference ->
val toolObject = ToolObject(
objects = reference.goals,
namingStrategy = { "${reference.name.lowercase()}_$it" },
filter = { goalName ->
// Only expose goals starting with "public"
goalName.startsWith("public")
}
)
McpToolExport.fromToolObject(toolObject).toolCallbacks
}
override fun infoString(verbose: Boolean?, indent: Int): String =
"PublicApiPublisher: ${toolCallbacks.size} public tools"
}LlmReference to MCP Tools: { .api }
// LlmReference structure (conceptual)
interface LlmReference {
val name: String // Agent name
val description: String // Agent description
val goals: List<Goal> // List of @Goal methods
}
interface Goal {
val name: String // Goal method name
val description: String // @Goal description
val inputType: Class<*> // Input parameter type
val outputType: Class<*> // Return type
fun invoke(input: Any): Any // Execute goal
}
// Conversion to MCP tool
McpToolExport.fromLlmReference(llmReference)
// Creates ToolCallback for each goal:
// - Tool name: "${agentName.lowercase()}_${goalName}"
// - Tool description: From @Goal annotation
// - Tool schema: From input type fields
// - Tool execution: Invokes goal methodDefault Naming Strategy:
Agent Name: UserManagementAgent
Goal Name: createUser
Result: usermanagementagent_createUserCustom Naming Strategy: { .api }
@Service
class CustomNamedAgentPublisher(
private val llmReferences: List<LlmReference>
) : McpExportToolCallbackPublisher {
override val toolCallbacks: List<ToolCallback>
get() = llmReferences.flatMap { reference ->
McpToolExport.fromLlmReference(
llmReference = reference,
namingStrategy = { goalName ->
// Custom format: api_v2_<agent>_<goal>
"api_v2_${reference.name.lowercase()}_$goalName"
}
).toolCallbacks
}
override fun infoString(verbose: Boolean?, indent: Int): String =
"CustomNamedAgentPublisher: ${toolCallbacks.size} tools"
}Namespace Collision Prevention: { .api }
@Service
class NamespaceAwarePublisher(
private val llmReferences: List<LlmReference>
) : McpExportToolCallbackPublisher {
override val toolCallbacks: List<ToolCallback>
get() {
val toolsByName = mutableMapOf<String, ToolCallback>()
llmReferences.forEach { reference ->
val agentPrefix = generateUniquePrefix(reference)
McpToolExport.fromLlmReference(
llmReference = reference,
namingStrategy = { goalName ->
"${agentPrefix}_$goalName"
}
).toolCallbacks.forEach { tool ->
if (toolsByName.containsKey(tool.name)) {
logger.warn("Duplicate tool name: ${tool.name}")
} else {
toolsByName[tool.name] = tool
}
}
}
return toolsByName.values.toList()
}
private fun generateUniquePrefix(reference: LlmReference): String {
// Use package name + class name for uniqueness
return "${reference.packageName}_${reference.simpleName}".lowercase()
}
override fun infoString(verbose: Boolean?, indent: Int): String =
"NamespaceAwarePublisher: ${toolCallbacks.size} tools"
companion object {
private val logger = LoggerFactory.getLogger(NamespaceAwarePublisher::class.java)
}
}Input Type to JSON Schema: { .api }
// Input type with annotations
data class CreateTaskInput(
@JsonPropertyDescription("Task title (required, max 100 characters)")
val title: String,
@JsonPropertyDescription("Detailed task description")
val description: String,
@JsonPropertyDescription("Priority level: 1 (low) to 5 (high)")
val priority: Int = 3,
@JsonPropertyDescription("Assigned user ID (optional)")
val assigneeId: String? = null,
@JsonPropertyDescription("Due date in ISO-8601 format")
val dueDate: String? = null
)
// Generated JSON schema (conceptual)
{
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Task title (required, max 100 characters)"
},
"description": {
"type": "string",
"description": "Detailed task description"
},
"priority": {
"type": "integer",
"description": "Priority level: 1 (low) to 5 (high)",
"default": 3
},
"assigneeId": {
"type": "string",
"description": "Assigned user ID (optional)"
},
"dueDate": {
"type": "string",
"description": "Due date in ISO-8601 format"
}
},
"required": ["title", "description"]
}Best Practices for Input Types: { .api }
import com.fasterxml.jackson.annotation.JsonPropertyDescription
import javax.validation.constraints.*
data class WellDocumentedInput(
@JsonPropertyDescription("User email address (must be valid email format)")
@Email
val email: String,
@JsonPropertyDescription("User age (must be between 18 and 120)")
@Min(18)
@Max(120)
val age: Int,
@JsonPropertyDescription("User role: 'admin', 'user', or 'viewer'")
@Pattern(regexp = "^(admin|user|viewer)$")
val role: String = "user",
@JsonPropertyDescription("Optional phone number in E.164 format")
val phoneNumber: String? = null,
@JsonPropertyDescription("Tags for categorization (max 10 tags)")
@Size(max = 10)
val tags: List<String> = emptyList(),
@JsonPropertyDescription("Metadata as key-value pairs")
val metadata: Map<String, String> = emptyMap()
)Core Interface: { .api }
interface LlmReference {
val name: String
val description: String
val goals: List<GoalDefinition>
val packageName: String
val simpleName: String
}
interface GoalDefinition {
val name: String
val description: String
val inputType: Class<*>
val outputType: Class<*>
fun invoke(input: Any): Any
}Combine Multiple Agents: { .api }
@Service
class MultiAgentPublisher(
private val llmReferences: List<LlmReference>
) : McpExportToolCallbackPublisher {
override val toolCallbacks: List<ToolCallback>
get() = McpToolExport.fromLlmReferences(
llmReferences = llmReferences,
namingStrategy = { toolName ->
// Global versioning prefix
"v1_$toolName"
}
).toolCallbacks
override fun infoString(verbose: Boolean?, indent: Int): String =
"MultiAgentPublisher: ${toolCallbacks.size} tools from " +
"${llmReferences.size} agents"
}Per-Agent Customization: { .api }
@Service
class CustomizedMultiAgentPublisher(
private val llmReferences: List<LlmReference>
) : McpExportToolCallbackPublisher {
private val agentConfigs = mapOf(
"UserAgent" to AgentConfig(prefix = "user", expose = true),
"AdminAgent" to AgentConfig(prefix = "admin", expose = true),
"InternalAgent" to AgentConfig(prefix = "internal", expose = false)
)
override val toolCallbacks: List<ToolCallback>
get() = llmReferences
.mapNotNull { reference ->
val config = agentConfigs[reference.simpleName]
if (config?.expose == true) {
reference to config
} else {
null
}
}
.flatMap { (reference, config) ->
McpToolExport.fromLlmReference(
llmReference = reference,
namingStrategy = { goalName ->
"${config.prefix}_$goalName"
}
).toolCallbacks
}
override fun infoString(verbose: Boolean?, indent: Int): String =
"CustomizedMultiAgentPublisher: ${toolCallbacks.size} tools"
data class AgentConfig(val prefix: String, val expose: Boolean)
}Embabel agents support different autonomy levels that control their behavior:
Autonomy Configuration: { .api }
@Agent
class AutomatedAgent {
@Goal(
name = "processData",
description = "Process data with configurable autonomy",
autonomy = Autonomy.SUPERVISED // Requires confirmation
)
fun processData(input: ProcessInput): ProcessOutput {
// Agent implementation
return ProcessOutput(result = "processed")
}
@Goal(
name = "analyzeData",
description = "Analyze data autonomously",
autonomy = Autonomy.AUTONOMOUS // Runs without confirmation
)
fun analyzeData(input: AnalyzeInput): AnalyzeOutput {
// Agent implementation
return AnalyzeOutput(insights = listOf())
}
}Stateful Agents: { .api }
@Agent
@Scope("prototype") // New instance per invocation
class StatefulAgent {
private val sessionState = mutableMapOf<String, Any>()
@Goal(name = "initializeSession", description = "Initialize agent session")
fun initializeSession(input: InitInput): InitOutput {
sessionState["userId"] = input.userId
sessionState["timestamp"] = System.currentTimeMillis()
return InitOutput(sessionId = generateSessionId())
}
@Goal(name = "getSessionInfo", description = "Get current session information")
fun getSessionInfo(input: SessionInput): SessionOutput {
return SessionOutput(
userId = sessionState["userId"] as? String,
timestamp = sessionState["timestamp"] as? Long
)
}
}McpAwareGoalTool: Interface for goals aware of MCP context { .api }
interface McpAwareGoalTool {
fun executeMcp(input: Any, context: McpContext): Any
}
data class McpContext(
val clientId: String,
val requestId: String,
val metadata: Map<String, String>
)Implementation: { .api }
@Agent
class McpAwareAgent : McpAwareGoalTool {
@Goal(
name = "processWithContext",
description = "Process data with MCP context awareness"
)
override fun executeMcp(input: Any, context: McpContext): Any {
logger.info("Processing request ${context.requestId} from ${context.clientId}")
val typedInput = input as ProcessInput
// Use context for logging, metrics, etc.
metricsService.recordRequest(context.clientId)
val result = processData(typedInput)
return ProcessOutput(
result = result,
requestId = context.requestId
)
}
private fun processData(input: ProcessInput): String {
// Business logic
return "processed"
}
companion object {
private val logger = LoggerFactory.getLogger(McpAwareAgent::class.java)
}
}Publisher with Context: { .api }
@Service
class ContextAwarePublisher(
private val llmReferences: List<LlmReference>
) : McpExportToolCallbackPublisher {
override val toolCallbacks: List<ToolCallback>
get() = llmReferences.flatMap { reference ->
McpToolExport.fromLlmReference(reference).toolCallbacks.map { callback ->
ContextPropagatingToolCallback(callback)
}
}
override fun infoString(verbose: Boolean?, indent: Int): String =
"ContextAwarePublisher: ${toolCallbacks.size} tools"
private class ContextPropagatingToolCallback(
private val delegate: ToolCallback
) : ToolCallback by delegate {
override fun call(functionArguments: String): String {
val context = McpContext(
clientId = extractClientId(),
requestId = generateRequestId(),
metadata = extractMetadata()
)
// If delegate is McpAwareGoalTool, pass context
return if (delegate is McpAwareGoalTool) {
val input = parseInput(functionArguments)
val result = delegate.executeMcp(input, context)
serializeOutput(result)
} else {
delegate.call(functionArguments)
}
}
private fun extractClientId(): String = "client-${System.currentTimeMillis()}"
private fun generateRequestId(): String = UUID.randomUUID().toString()
private fun extractMetadata(): Map<String, String> = emptyMap()
private fun parseInput(args: String): Any = TODO()
private fun serializeOutput(result: Any): String = TODO()
}
}Resource Change Notification: { .api }
interface McpResourceUpdatingListener {
fun onResourceUpdated(resourceUri: String, newContent: String)
fun onResourceDeleted(resourceUri: String)
}
@Service
class AgentResourceListener : McpResourceUpdatingListener {
override fun onResourceUpdated(resourceUri: String, newContent: String) {
logger.info("Resource updated: $resourceUri")
// Notify relevant agents
agentNotifier.notifyResourceChange(resourceUri, newContent)
}
override fun onResourceDeleted(resourceUri: String) {
logger.info("Resource deleted: $resourceUri")
// Clear agent caches
agentCache.invalidate(resourceUri)
}
companion object {
private val logger = LoggerFactory.getLogger(AgentResourceListener::class.java)
}
}Dynamic Resource Publishing: { .api }
@Service
class DynamicAgentResourcePublisher(
private val llmReferences: List<LlmReference>,
private val resourceListener: McpResourceUpdatingListener
) : McpAsyncResourcePublisher {
private val resourceCache = ConcurrentHashMap<String, String>()
override fun resources(): List<AsyncResourceSpecification> {
return llmReferences.map { reference ->
createAgentResource(reference)
}
}
private fun createAgentResource(reference: LlmReference): AsyncResourceSpecification {
val uri = "app://agents/${reference.simpleName}/info"
return AsyncResourceSpecification(
Resource(uri, reference.simpleName, reference.description, "application/json", null)
) { exchange, request ->
Mono.fromCallable {
val content = generateAgentInfo(reference)
// Update cache
val oldContent = resourceCache.put(uri, content)
if (oldContent != content) {
resourceListener.onResourceUpdated(uri, content)
}
ReadResourceResult(
listOf(
TextResourceContents(uri, "application/json", content)
)
)
}
}
}
private fun generateAgentInfo(reference: LlmReference): String {
return objectMapper.writeValueAsString(
mapOf(
"name" to reference.name,
"description" to reference.description,
"goals" to reference.goals.map { goal ->
mapOf(
"name" to goal.name,
"description" to goal.description
)
}
)
)
}
override fun infoString(verbose: Boolean?, indent: Int): String =
"DynamicAgentResourcePublisher: ${resources().size} resources"
companion object {
private val objectMapper = ObjectMapper()
}
}Dynamic Agent Creation: { .api }
@Service
class AgentFactory {
fun createAgent(type: AgentType, config: AgentConfig): LlmReference {
return when (type) {
AgentType.USER_MANAGEMENT -> createUserManagementAgent(config)
AgentType.DATA_PROCESSING -> createDataProcessingAgent(config)
AgentType.ANALYTICS -> createAnalyticsAgent(config)
}
}
private fun createUserManagementAgent(config: AgentConfig): LlmReference {
// Create and configure agent
return TODO()
}
}
@Service
class DynamicAgentPublisher(
private val agentFactory: AgentFactory
) : McpExportToolCallbackPublisher {
override val toolCallbacks: List<ToolCallback>
get() {
val agents = listOf(
agentFactory.createAgent(AgentType.USER_MANAGEMENT, defaultConfig),
agentFactory.createAgent(AgentType.DATA_PROCESSING, defaultConfig)
)
return agents.flatMap { agent ->
McpToolExport.fromLlmReference(agent).toolCallbacks
}
}
override fun infoString(verbose: Boolean?, indent: Int): String =
"DynamicAgentPublisher: ${toolCallbacks.size} tools"
private val defaultConfig = AgentConfig()
}Composite Agent Pattern: { .api }
@Agent
class CompositeAgent(
private val userAgent: UserManagementAgent,
private val dataAgent: DataProcessingAgent
) {
@Goal(
name = "createUserWithData",
description = "Create user and initialize their data"
)
fun createUserWithData(input: CompositeInput): CompositeOutput {
// Coordinate multiple agents
val userResult = userAgent.createUser(
CreateUserInput(input.email, input.name, input.role)
)
val dataResult = dataAgent.initializeData(
InitDataInput(userResult.userId, input.initialData)
)
return CompositeOutput(
userId = userResult.userId,
dataInitialized = dataResult.success
)
}
}Sequential Agent Execution: { .api }
@Service
class AgentPipeline(
private val llmReferences: List<LlmReference>
) {
fun executePipeline(stages: List<PipelineStage>, initialInput: Any): Any {
var currentInput = initialInput
for (stage in stages) {
val agent = findAgent(stage.agentName)
val goal = findGoal(agent, stage.goalName)
currentInput = goal.invoke(currentInput)
}
return currentInput
}
private fun findAgent(name: String): LlmReference {
return llmReferences.find { it.name == name }
?: throw IllegalArgumentException("Agent not found: $name")
}
private fun findGoal(agent: LlmReference, goalName: String): GoalDefinition {
return agent.goals.find { it.name == goalName }
?: throw IllegalArgumentException("Goal not found: $goalName")
}
}
data class PipelineStage(val agentName: String, val goalName: String)Version-Aware Agent Exposure: { .api }
@Service
class VersionedAgentPublisher(
private val llmReferences: List<LlmReference>
) : McpExportToolCallbackPublisher {
private val versionedAgents = mapOf(
"v1" to listOf("UserAgent", "DataAgent"),
"v2" to listOf("UserAgentV2", "DataAgentV2", "AnalyticsAgent")
)
override val toolCallbacks: List<ToolCallback>
get() = versionedAgents.flatMap { (version, agentNames) ->
llmReferences
.filter { it.simpleName in agentNames }
.flatMap { reference ->
McpToolExport.fromLlmReference(
llmReference = reference,
namingStrategy = { goalName ->
"${version}_${reference.simpleName.lowercase()}_$goalName"
}
).toolCallbacks
}
}
override fun infoString(verbose: Boolean?, indent: Int): String =
"VersionedAgentPublisher: ${toolCallbacks.size} tools across " +
"${versionedAgents.size} versions"
}Defer Expensive Operations: { .api }
@Service
class LazyAgentPublisher(
private val llmReferences: List<LlmReference>
) : McpExportToolCallbackPublisher {
override val toolCallbacks: List<ToolCallback> by lazy {
logger.info("Initializing agent tools...")
val start = System.currentTimeMillis()
val tools = llmReferences.flatMap { reference ->
McpToolExport.fromLlmReference(reference).toolCallbacks
}
val duration = System.currentTimeMillis() - start
logger.info("Initialized ${tools.size} tools in ${duration}ms")
tools
}
override fun infoString(verbose: Boolean?, indent: Int): String =
"LazyAgentPublisher: ${toolCallbacks.size} tools"
companion object {
private val logger = LoggerFactory.getLogger(LazyAgentPublisher::class.java)
}
}Cache Agent Invocations: { .api }
@Service
class CachedAgentPublisher(
private val llmReferences: List<LlmReference>,
private val cacheManager: CacheManager
) : McpExportToolCallbackPublisher {
private val cache = cacheManager.getCache("agent-results")
override val toolCallbacks: List<ToolCallback>
get() = llmReferences.flatMap { reference ->
McpToolExport.fromLlmReference(reference).toolCallbacks.map { callback ->
CachedToolCallback(callback, cache)
}
}
override fun infoString(verbose: Boolean?, indent: Int): String =
"CachedAgentPublisher: ${toolCallbacks.size} tools"
private class CachedToolCallback(
private val delegate: ToolCallback,
private val cache: Cache?
) : ToolCallback by delegate {
override fun call(functionArguments: String): String {
val cacheKey = "${delegate.name}:$functionArguments"
return cache?.get(cacheKey, String::class.java)
?: run {
val result = delegate.call(functionArguments)
cache?.put(cacheKey, result)
result
}
}
}
}Execute Multiple Agents Concurrently: { .api }
@Service
class ParallelAgentExecutor(
private val llmReferences: List<LlmReference>
) {
fun executeParallel(requests: List<AgentRequest>): List<AgentResponse> {
return requests.parallelStream()
.map { request ->
val agent = findAgent(request.agentName)
val goal = findGoal(agent, request.goalName)
val result = goal.invoke(request.input)
AgentResponse(
agentName = request.agentName,
goalName = request.goalName,
result = result
)
}
.toList()
}
private fun findAgent(name: String): LlmReference = TODO()
private fun findGoal(agent: LlmReference, goalName: String): GoalDefinition = TODO()
}
data class AgentRequest(val agentName: String, val goalName: String, val input: Any)
data class AgentResponse(val agentName: String, val goalName: String, val result: Any)