How to Implement Goal Export with @Export(remote = true) for Platform-Wide Discovery in Embabel
Use the export attribute of @AchievesGoal with remote = true to automatically convert agent goals into MCP tools that any remote client can discover and invoke across the Embabel platform.
The embabel/embabel-agent framework treats every goal-achieving action as a potential remote tool. By configuring goal export with @Export(remote = true), you transform local @AchievesGoal methods into platform-wide resources discoverable via the Model-Context-Protocol (MCP) server. This allows distributed clients to leverage your agent's capabilities without direct coupling to the implementation.
Understanding the @Export Annotation Attributes
The @Export annotation, defined in [Export.java](https://github.com/embabel/embabel-agent/blob/main/embabel-agent-api/src/main/java/com/embabel/agent/api/annotation/Export.java), controls how goals are exposed through the export attribute of AchievesGoal. The annotation supports four key attributes:
remote– When set totrue, the framework wraps the goal in an AgentTool and registers it with the MCP server for cross-platform discovery.local– Whentrue(default), the goal remains usable within the same agent process.name– Overrides the automatically generated tool name used in MCP tool listings.startingInputTypes– Declares input types (e.g.,UserInput.class) that remote clients must provide when invoking the tool.
How Platform-Wide Export Works
The export mechanism follows a four-stage pipeline implemented in the framework's annotation processing layer:
- Agent Scanning – The framework scans classes annotated with
@Agentto identify methods marked with@AchievesGoal. - Goal Instantiation – For each annotated method, the system creates a
Goalobject representing the logical objective. - Tool Conversion – If
export = @Export(remote = true)is present, the goal is automatically converted into anAgentTooland bound to the MCP server, the central discovery service. - Remote Discovery – Clients query the MCP server to retrieve available tools, including their names and required input schemas, then invoke them via standard MCP request formats.
Implementing Remote Goal Export
To expose a goal platform-wide, nest the @Export annotation within @AchievesGoal and set remote = true.
Java Implementation
The following agent demonstrates the pattern using NewsDigest operations:
@Agent(description = "News digest generator")
@SecureAgentTool("hasAuthority('news:read')")
public class NewsDigestAgent {
@Action
public NewsTopic extractTopic(UserInput input, OperationContext ctx) {
// Extraction logic
return new NewsTopic(...);
}
@AchievesGoal(
description = "Produce a curated news digest",
export = @Export(
remote = true,
name = "newsDigest",
startingInputTypes = {UserInput.class}
)
)
@Action
public NewsDigest produceDigest(NewsTopic topic, OperationContext ctx) {
// Digest generation logic
return new NewsDigest(...);
}
}
Kotlin Implementation
The same pattern applies in Kotlin, using array literals for startingInputTypes:
@Agent(description = "News digest generator")
@SecureAgentTool("hasAuthority('news:read')")
class NewsDigestAgent {
@Action
fun extractTopic(input: UserInput, ctx: OperationContext): NewsTopic {
return NewsTopic(...)
}
@AchievesGoal(
description = "Produce a curated news digest",
export = Export(
remote = true,
name = "newsDigest",
startingInputTypes = [UserInput::class]
)
)
@Action
fun produceDigest(topic: NewsTopic, ctx: OperationContext): NewsDigest {
return NewsDigest(...)
}
}
Securing Exported Tools
When exposing goals remotely, apply the @SecureAgentTool annotation to enforce authorization. You can place this on the agent class or specific methods. The security expression (e.g., "hasAuthority('news:read')") is evaluated before the tool executes, preventing unauthorized remote access to sensitive operations.
Declaring Input Types for Remote Clients
The startingInputTypes attribute enables MCP clients to automatically generate UI prompts for required domain objects. By declaring startingInputTypes = {UserInput.class}, you inform remote clients that the tool expects user-provided input, allowing the client to collect this data before invoking the agent's goal.
Validation and Testing
The framework's test suite includes examples of remote export configurations. In [EmbabelMockitoIntegrationTestStreamingTest.java](https://github.com/embabel/embabel-agent/blob/main/embabel-agent-test-support/embabel-agent-test/src/test/java/com/embabel/agent/test/integration/EmbabelMockitoIntegrationTestStreamingTest.java), the following pattern validates the export mechanism:
@AchievesGoal(
description = "Write and review a story",
export = @Export(remote = true, name = "writeAndReviewStory")
)
@Action
public StoryResult writeAndReviewStory(UserInput input, OperationContext ctx) {
// Implementation
}
Summary
- Goal export with
@Export(remote = true)converts@AchievesGoalmethods into MCP tools discoverable by any platform client. - The framework handles automatic conversion from
GoaltoAgentToolduring annotation processing. - Use
startingInputTypesto declare input requirements for remote client UI generation. - Apply
@SecureAgentToolto protect exported goals from unauthorized remote invocation. - Configuration is defined in [
Export.java](https://github.com/embabel/embabel-agent/blob/main/embabel-agent-api/src/main/java/com/embabel/agent/api/annotation/Export.java) and consumed by the MCP server registry.
Frequently Asked Questions
What is the difference between local and remote goal export?
Local export (local = true) makes the goal available for invocation within the same agent process, while remote export (remote = true) publishes the goal as an MCP tool that external clients can discover and call across the network. You can enable both simultaneously for maximum flexibility.
How does the MCP server discover exported goals?
During application startup, the framework scans for @Agent classes and processes @AchievesGoal annotations. When remote = true is detected, the goal is wrapped in an AgentTool instance and registered with the central MCP server, which maintains a registry of all platform-wide tools.
Can I customize the tool name shown to remote clients?
Yes. Use the name attribute inside @Export to override the default tool name. For example, @Export(remote = true, name = "customToolName") ensures remote clients see "customToolName" instead of the auto-generated name derived from the method signature.
How do I handle security for remotely exported goals?
Add the @SecureAgentTool annotation to your agent class or method, providing a SpEL expression that evaluates the user's authorities. The framework checks this expression before executing the tool, ensuring only authorized clients can invoke the remotely exported goal.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →