### Real-World Example: Chatbot Configuration (Java) Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/tools/page.adoc Integrate MCP tools into a Spring Boot application, handling missing tools gracefully and grouping related tools. This example demonstrates a production chatbot setup. ```java @Configuration public class ChatConfiguration { @Bean public McpToolFactory mcpToolFactory(List clients) { return new SpringAiMcpToolFactory(clients); } @Bean public CommonTools commonTools(McpToolFactory mcpToolFactory) { var deferMessage = "Use this tool only after trying local sources"; var tools = new LinkedList<>(); // Single MCP tool - gracefully handle missing tools var braveSearch = mcpToolFactory.toolByName("brave_web_search"); if (braveSearch != null) { tools.add(braveSearch.withNote(deferMessage)); } // UnfoldingTool grouping related Wikipedia MCP tools var wikipediaTool = mcpToolFactory.unfoldingByName( "wikipedia", "Search and find content from Wikipedia: " + deferMessage, Set.of("search_wikipedia", "get_article", "get_related_topics", "get_summary") ); if (!wikipediaTool.getInnerTools().isEmpty()) { tools.add(wikipediaTool); } return new CommonTools(tools); } } ``` -------------------------------- ### Webhook Integration Example Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/invoking/page.adoc Example of how to handle incoming webhooks (e.g., from JIRA) to create and start agent processes. ```APIDOC ## POST /webhook/jira/issue-created ### Description Handles incoming JIRA issue created webhooks to initiate an agent process. ### Method POST ### Endpoint /webhook/jira/issue-created ### Parameters #### Request Body - **payload** (JiraWebhookPayload) - Required - The payload from the JIRA webhook. ### Request Example { "issue": { "key": "PROJ-123", "fields": { "summary": "Example Summary", "description": "This is an example issue description." } } } ### Response #### Success Response (202 Accepted) Returns the process ID and URLs for status tracking. - **processId** (string) - The ID of the created agent process. - **statusUrl** (string) - URL to check the process status. - **sseUrl** (string) - URL for Server-Sent Events for real-time updates. #### Response Example { "processId": "some-process-id", "statusUrl": "/api/v1/process/some-process-id", "sseUrl": "/events/process/some-process-id" } ``` -------------------------------- ### Real-World Example: Chatbot Configuration (Kotlin) Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/tools/page.adoc Integrate MCP tools into a Spring Boot application using Kotlin, handling missing tools gracefully and grouping related tools. This example demonstrates a production chatbot setup. ```kotlin @Configuration class ChatConfiguration { @Bean fun mcpToolFactory(clients: List): McpToolFactory = SpringAiMcpToolFactory(clients) @Bean fun commonTools(mcpToolFactory: McpToolFactory): CommonTools { val deferMessage = "Use this tool only after trying local sources" val tools = mutableListOf() // Single MCP tool - gracefully handle missing tools mcpToolFactory.toolByName("brave_web_search")?.let { braveSearch -> tools.add(braveSearch.withNote(deferMessage)) } // UnfoldingTool grouping related Wikipedia MCP tools val wikipediaTool = mcpToolFactory.unfoldingByName( name = "wikipedia", description = "Search and find content from Wikipedia: $deferMessage", toolNames = setOf("search_wikipedia", "get_article", "get_related_topics", "get_summary") ) if (wikipediaTool.innerTools.isNotEmpty()) { tools.add(wikipediaTool) } return CommonTools(tools) } } ``` -------------------------------- ### Direct AgentProcess Creation and Start (Kotlin) Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/invoking/page.adoc Shows how to create an AgentProcess directly in Kotlin, configure options, and initiate asynchronous execution. This mirrors the Java example for direct process management. ```kotlin @Controller @RequestMapping("/journey") class JourneyController( private val agentPlatform: AgentPlatform ) { @PostMapping("/plan") fun planJourney(@ModelAttribute form: JourneyPlanForm, model: Model): String { // Convert form to domain objects val travelBrief = TravelBrief( form.from, form.to, form.departureDate, form.returnDate, form.brief ) // Find the appropriate agent val agent = agentPlatform.agents() .filter { it.name.lowercase().contains("travel") } .firstOrNull() ?: throw IllegalStateException("No travel agent found") // Create the agent process with input bindings val agentProcess = agentPlatform.createAgentProcessFrom( agent, ProcessOptions( verbosity = Verbosity(showPrompts = true), budget = Budget.DEFAULT // or custom budget ), travelBrief // Vararg inputs bound to blackboard ) // Start the process asynchronously agentPlatform.start(agentProcess) // Add process ID to model for status polling model.addAttribute("processId", agentProcess.id) model.addAttribute("travelBrief", travelBrief) // Return a view that polls /api/v1/process/{processId} for status return "processing" } } ``` -------------------------------- ### Clone and run Embabel examples Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/getting-started/running/page.adoc Use these commands to download the example repository and launch the shell script for Java or Kotlin. ```bash # Clone and run examples git clone https://github.com/embabel/embabel-agent-examples cd embabel-agent-examples/scripts/java ./shell.sh ``` -------------------------------- ### Adding Multiple Examples with varargs Syntax (Kotlin) Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/testing/page.adoc Shows the Kotlin equivalent of using varargs with `withExamples` for inline example provision. This offers a concise way to add a few examples directly in the code. ```kotlin val result = context.ai() .withDefaultLlm() .creating(ChannelEditPlan::class.java) .withExamples( CreationExample("Example 1", ChannelEditPlan(1, "Bass")), CreationExample("Example 2", ChannelEditPlan(2, "Drums")), CreationExample("Example 3", ChannelEditPlan(3, "Keys")) ) .fromPrompt("Analyze the request") ``` -------------------------------- ### Clone and Run Example Agents Source: https://github.com/embabel/embabel-agent/blob/main/README.md Clone the example repository and navigate to the scripts directory to execute shell scripts for running example agents. ```bash # Clone and run examples git clone https://github.com/embabel/embabel-agent-examples cd embabel-agent-examples/scripts/kotlin ./shell.sh ``` -------------------------------- ### Adding Multiple Examples with varargs Syntax (Java) Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/testing/page.adoc Illustrates using the vararg capability of `withExamples` in Java to pass examples directly as inline arguments. This is convenient for a small, fixed number of examples. ```java var result = context.ai() .withDefaultLlm() .creating(ChannelEditPlan.class) .withExamples( new CreationExample<>("Example 1", new ChannelEditPlan(1, "Bass")), new CreationExample<>("Example 2", new ChannelEditPlan(2, "Drums")), new CreationExample<>("Example 3", new ChannelEditPlan(3, "Keys")) ) .fromPrompt("Analyze the request"); ``` -------------------------------- ### Adding Multiple Examples with withExamples() from a List Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/testing/page.adoc Shows how to pass a list of `CreationExample` objects to the `withExamples` method. This is ideal when examples are dynamically loaded or stored in collections. ```java import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; import org.embabel.core.context.FakeOperationContext; import org.embabel.core.model.CreationExample; import org.embabel.core.model.creation.ChannelEditPlan; import java.util.List; class CreationExampleTest { @Test void shouldAddMultipleExamplesFromList() { var context = FakeOperationContext.create(); var expectedPlan = new ChannelEditPlan(1, "Lead Vox"); context.expectResponse(expectedPlan); // Create a list of examples (could be loaded from configuration) var examples = List.of( new CreationExample<>("Rename to Bass", new ChannelEditPlan(1, "Bass")), new CreationExample<>("Rename to Drums", new ChannelEditPlan(2, "Drums")), new CreationExample<>("Rename to Keys", new ChannelEditPlan(3, "Keys")), new CreationExample<>("Rename to Vocals", new ChannelEditPlan(4, "Vocals")) ); var result = context.ai() .withDefaultLlm() .creating(ChannelEditPlan.class) .withExamples(examples) // Pass all examples at once .fromPrompt("Analyze the request"); assertEquals(expectedPlan, result); // Verify all examples were added var promptContributors = context.getLlmInvocations().getFirst() .getInteraction().getPromptContributors(); assertTrue(promptContributors.size() >= 4); } } ``` -------------------------------- ### Create Embabel Project from Template Source: https://github.com/embabel/embabel-agent/wiki/Home Use uvx to quickly create a new Embabel project from a template. This is the fastest way to get started. ```bash uvx --from git+https://github.com/embabel/project-creator.git project-creator ``` -------------------------------- ### Install Maven on Ubuntu Source: https://github.com/embabel/embabel-agent/wiki/Development-Environment-Setup-‐-Linux Installs the Apache Maven build tool. ```bash sudo apt install maven mvn --version ``` -------------------------------- ### System Property Configuration Example Source: https://github.com/embabel/embabel-agent/wiki/Profiles-Migration-(Completed) Example of setting embel agent infrastructure Neo4j URI using a system property. ```text -Dembabel.agent.infrastructure.neo4j.uri=bolt://test:7687 ``` -------------------------------- ### Agent Shell Session Example Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-starters/embabel-agent-starter-shell/README.md Demonstration of running the application and executing agent commands. ```bash $ ./mvnw spring-boot:run ╔═══════════════════════════════════════════════════════════╗ ║ Embabel Agent Shell ║ ╚═══════════════════════════════════════════════════════════╝ shell:> agents Agents: ───────────────────────────────────────── StarNewsFinder: Find news based on a person's star sign Researcher: Research a topic using multiple LLMs ... shell:> x "Find horoscope news for Alice who is a Gemini" [Executing StarNewsFinder...] ... shell:> bb Blackboard contents: userInput: UserInput(text="Find horoscope news for Alice who is a Gemini") person: Person(name="Alice") starSign: StarSign.GEMINI ... shell:> exit Goodbye! ``` -------------------------------- ### Install Ollama for Local AI Models Source: https://github.com/embabel/embabel-agent/wiki/Quick-Start-Guide Install Ollama to run local AI models without needing API keys. This includes pulling a model and starting the Ollama server. ```bash # Install Ollama curl -fsSL https://ollama.ai/install.sh | sh # Pull a model (choose one) ollama pull llama3.2 # General purpose ollama pull codellama # Code-focused ollama pull llama3.2:1b # Lightweight # Start Ollama server ollama serve ``` -------------------------------- ### Create Story with Example Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/types/page.adoc Generates a story using a default LLM and web tools, incorporating an example to guide the LLM. Suitable for creative text generation tasks. ```java var story = context.ai() .withDefaultLlm() .withToolGroup(CoreToolGroups.WEB) .creating(Story.class) .withExample("A children's story", new Story("Once upon a time...")) // <1> .fromPrompt("Create a story about: " + input.getContent()); ``` ```kotlin val story = context.ai() .withDefaultLlm() .withToolGroup(CoreToolGroups.WEB) .creating(Story::class.java) .withExample("A children's story", Story("Once upon a time...")) // <1> .fromPrompt("Create a story about: ${input.content}") ``` -------------------------------- ### Include Examples in Prompt (Java) Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/testing/page.adoc Tests that examples provided via `withExample()` are correctly added as prompt contributors. Verifies the count of prompt contributors after an AI call. ```java import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import dev.embabel.api.model.ChannelEditPlan; import dev.embabel.test.FakeOperationContext; class FakePromptRunnerTest { @Test void shouldIncludeExamplesInPrompt() { var context = FakeOperationContext.create(); var expectedPlan = new ChannelEditPlan(1, "Lead Vox"); context.expectResponse(expectedPlan); var result = context.ai() .withLlm(llmSelectionService.selectOptimalLlm()) // Assuming llmSelectionService is available .withId("analyze-edit-request") .creating(ChannelEditPlan.class) .withExample("Rename channel 1", new ChannelEditPlan(1, "Bass")) .withExample("Rename channel 2", new ChannelEditPlan(2, "Drums")) .fromPrompt("Analyze the edit request"); assertEquals(expectedPlan, result); // Verify examples were added as prompt contributors var promptContributors = context.getLlmInvocations().getFirst() .getInteraction().getPromptContributors(); assertTrue(promptContributors.size() >= 2, "Examples should be added as prompt contributors"); } } ``` -------------------------------- ### Clone Embabel Agent Examples Source: https://github.com/embabel/embabel-agent/wiki/Home Clone the Embabel agent examples repository to explore pre-built agent functionalities and scripts. Navigate to the Kotlin scripts directory and execute shell scripts for setup. ```bash git clone https://github.com/embabel/embabel-agent-examples cd embabel-agent-examples/scripts/kotlin ./shell.sh ``` -------------------------------- ### Java Web Application Example: Trip Planning Controller Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/invoking/page.adoc A Spring Boot controller demonstrating synchronous and asynchronous trip planning using AgentInvocation. It handles POST requests to plan trips and GET requests to check trip status. ```java @Controller public class TripPlanningController { private final AgentPlatform agentPlatform; private final ConcurrentHashMap> activeJobs = new ConcurrentHashMap<>(); private static final Logger logger = LoggerFactory.getLogger(TripPlanningController.class); private static final ConcurrentHashMap tripResultCache = new ConcurrentHashMap<>(); public TripPlanningController(AgentPlatform agentPlatform) { this.agentPlatform = agentPlatform; } @PostMapping("/plan-trip") public String planTrip( @ModelAttribute TripRequest tripRequest, Model model) { // Generate unique job ID for tracking String jobId = UUID.randomUUID().toString(); // Create agent invocation with custom options var processOptions = new ProcessOptions() .withVerbosity(new Verbosity().withShowPrompts(true)); var invocation = AgentInvocation.builder(agentPlatform) .options(processOptions) .build(TripPlan.class); // Start async agent execution CompletableFuture future = invocation.invokeAsync(tripRequest); activeJobs.put(jobId, future); // Set up completion handler future.whenComplete((result, throwable) -> { if (throwable != null) { logger.error("Trip planning failed for job {}", jobId, throwable); } else { logger.info("Trip planning completed for job {}", jobId); } }); model.addAttribute("jobId", jobId); model.addAttribute("tripRequest", tripRequest); // Return htmx template that will poll for results return "trip-planning-progress"; } @GetMapping("/trip-status/{jobId}") @ResponseBody public ResponseEntity> getTripStatus(@PathVariable String jobId) { CompletableFuture future = activeJobs.get(jobId); if (future == null) { return ResponseEntity.notFound().build(); } if (future.isDone()) { try { TripPlan tripPlan = future.get(); activeJobs.remove(jobId); return ResponseEntity.ok(Map.of( "status", "completed", "result", tripPlan, "redirect", "/trip-result/" + jobId )); } catch (Exception e) { activeJobs.remove(jobId); return ResponseEntity.ok(Map.of( "status", "failed", "error", e.getMessage() )); } } else if (future.isCancelled()) { activeJobs.remove(jobId); return ResponseEntity.ok(Map.of("status", "cancelled")); } else { return ResponseEntity.ok(Map.of( ``` -------------------------------- ### Configure Shell Agent Application Source: https://github.com/embabel/embabel-agent/wiki/Spring-Integration-AutoConfiguration Setup for interactive agent development using the shell starter. ```kotlin @SpringBootApplication class ShellAgentApplication fun main(args: Array) { runApplication(*args) } ``` ```bash mvn spring-boot:run # Interactive shell starts automatically help execute "your agent request here" ``` -------------------------------- ### Include Examples in Prompt (Kotlin) Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/testing/page.adoc Tests that examples provided via `withExample()` are correctly added as prompt contributors. Verifies the count of prompt contributors after an AI call. ```kotlin import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test import dev.embabel.api.model.ChannelEditPlan import dev.embabel.test.FakeOperationContext class FakePromptRunnerTest { @Test fun `should include examples in prompt`() { val context = FakeOperationContext.create() val expectedPlan = ChannelEditPlan(1, "Lead Vox") context.expectResponse(expectedPlan) val result = context.ai() .withLlm(llmSelectionService.selectOptimalLlm()) // Assuming llmSelectionService is available .withId("analyze-edit-request") .creating(ChannelEditPlan::class.java) .withExample("Rename channel 1", ChannelEditPlan(1, "Bass")) .withExample("Rename channel 2", ChannelEditPlan(2, "Drums")) .fromPrompt("Analyze the edit request") assertEquals(expectedPlan, result) // Verify examples were added as prompt contributors val promptContributors = context.llmInvocations.first().interaction.promptContributors assertTrue(promptContributors.size >= 2, "Examples should be added as prompt contributors") } } ``` -------------------------------- ### Example Agent Log Sequence Source: https://github.com/embabel/embabel-agent/wiki/Development-and-Testing-of-REST-MVC‐enabled-Agent Illustrates a successful agent interaction flow from start to completion, showing controller entry points, agent action execution, and status transitions. ```text === POST /adventure/start - player: Player1 === === getChoice action starting for player: Player1 === Action method entering wait state: Awaitable response exception === Agent process status after run: WAITING === === POST /adventure/{id}/continue - choice: Castle === === onResponse called, resuming agent process === === processChoice action starting with choice: Castle === === processChoice action completed with result: You chose: Castle === === Agent process status after resume: COMPLETED === ``` -------------------------------- ### Direct AgentProcess Creation and Start (Java) Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/invoking/page.adoc Demonstrates creating an AgentProcess directly from an Agent, configuring process options, and starting it asynchronously. This is useful for webhooks or form submissions where an immediate response with a process ID is needed. ```java @Controller @RequestMapping("/journey") public class JourneyController { private final AgentPlatform agentPlatform; public JourneyController(AgentPlatform agentPlatform) { this.agentPlatform = agentPlatform; } @PostMapping("/plan") public String planJourney(@ModelAttribute JourneyPlanForm form, Model model) { // Convert form to domain objects TravelBrief travelBrief = new TravelBrief( form.getFrom(), form.getTo(), form.getDepartureDate(), form.getReturnDate(), form.getBrief() ); // Find the appropriate agent Agent agent = agentPlatform.agents().stream() .filter(a -> a.getName().toLowerCase().contains("travel")) .findFirst() .orElseThrow(() -> new IllegalStateException("No travel agent found")); // Create the agent process with input bindings AgentProcess agentProcess = agentPlatform.createAgentProcessFrom( agent, new ProcessOptions( new Verbosity().withShowPrompts(true), Budget.DEFAULT // or custom budget ), travelBrief // Vararg inputs bound to blackboard ); // Start the process asynchronously agentPlatform.start(agentProcess); // Add process ID to model for status polling model.addAttribute("processId", agentProcess.getId()); model.addAttribute("travelBrief", travelBrief); // Return a view that polls /api/v1/process/{processId} for status return "processing"; } } ``` -------------------------------- ### Complete Fluent API Chain Example (Java) Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/testing/page.adoc Presents a comprehensive Java test case demonstrating the full fluent API chain for agent creation, including LLM options, ID, system prompt, creation type, examples, and the final prompt execution. ```java import org.junit.jupiter.api.Test; import org.embabel.core.context.FakeOperationContext; import org.embabel.core.llm.LlmOptions; import org.embabel.core.model.creation.ComplexOutput; class FluentApiTest { @Test void shouldTestCompleteFluentApiChain() { var context = FakeOperationContext.create(); var expectedOutput = new ComplexOutput("analysis complete", 42); context.expectResponse(expectedOutput); // Production code pattern with full fluent API chain var result = context.ai() .withLlm(LlmOptions.withModel("gpt-4")) .withId("complex-analysis") .withSystemPrompt("You are an expert analyst") .creating(ComplexOutput.class) .withExample("Simple case", new ComplexOutput("basic", 1)); } } ``` -------------------------------- ### Start A2A Docker Profile Source: https://github.com/embabel/embabel-agent/blob/main/README.md Starts the A2A server using Docker Compose with the 'a2a' profile. Ensure the GOOGLE_STUDIO_API_KEY environment variable is set. ```bash docker compose --profile a2a up ``` -------------------------------- ### Environment Variable Configuration Example Source: https://github.com/embabel/embabel-agent/wiki/Profiles-Migration-(Completed) Example of setting embel agent infrastructure Neo4j URI using an environment variable. ```text EMBABEL_AGENT_INFRASTRUCTURE_NEO4J_URI=bolt://prod:7687 ``` -------------------------------- ### POST /start - Starting a New Agent Process Source: https://github.com/embabel/embabel-agent/wiki/Development-and-Testing-of-REST-MVC‐enabled-Agent Initiates a new agent process with the provided player name. This endpoint starts the agent's workflow and returns an initial awaitable response. ```APIDOC ## POST /start - Starting a New Agent Process ### Description Initiates a new agent process with the provided player name. This endpoint starts the agent's workflow and returns an initial awaitable response. ### Method POST ### Endpoint /start ### Parameters #### Request Body - **playerName** (string) - Required - The name of the player initiating the process. ### Request Example ```json { "playerName": "PlayerOne" } ``` ### Response #### Success Response (200) - **status** (string) - The current status of the agent process (expected to be WAITING initially). - **processId** (string) - The ID of the newly created agent process. - **awaitableId** (string) - The ID of the first awaitable item. - **prompt** (string) - The prompt to display to the user for the first interaction. - **options** (array) - The available options for the user's first choice. #### Response Example ```json { "status": "WAITING", "processId": "new-process-id-123", "awaitableId": "initial-awaitable-id", "prompt": "Welcome! Choose your adventure path:", "options": ["Forest", "Castle"] } ``` ``` -------------------------------- ### Install Git on Ubuntu Source: https://github.com/embabel/embabel-agent/wiki/Development-Environment-Setup-‐-Linux Updates package lists and installs the Git version control system. ```bash sudo apt update sudo apt install git git --version ``` -------------------------------- ### Example Log Output with MDC Correlation Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/integrations/page.adoc This is an example of how logs will appear with the configured Logback pattern, showing correlated agent and action information. ```text 14:23:45.123 [main] INFO c.e.MyService [runId=abc-123 agent=CustomerServiceAgent action=AnalyzeRequest] - Processing request ``` -------------------------------- ### Configure Basic Agent Application Source: https://github.com/embabel/embabel-agent/wiki/Spring-Integration-AutoConfiguration The minimal setup required to initialize the agent platform with GOAP planning support. ```kotlin @SpringBootApplication @EnableAgents class SimpleAgentApplication fun main(args: Array) { runApplication(*args) } ``` -------------------------------- ### Create and Start Agent Process (Kotlin) Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/invoking/page.adoc Creates and starts an agent process using the provided agent and issue details. Returns process ID and URLs for status tracking. ```kotlin val process = agentPlatform.createAgentProcessFrom( agent, ProcessOptions.DEFAULT, issue ) agentPlatform.start(process) // Return process ID for status tracking return ResponseEntity.accepted().body(mapOf( "processId" to process.id, "statusUrl" to "/api/v1/process/${process.id}", "sseUrl" to "/events/process/${process.id}" )) ``` -------------------------------- ### Install IntelliJ Toolbox Source: https://github.com/embabel/embabel-agent/wiki/Development-Environment-Setup-‐-Linux Downloads and extracts the JetBrains Toolbox archive to the local system. ```bash wget -c https://download.jetbrains.com/toolbox/jetbrains-toolbox-2.5.2.35332.tar.gz tar -xzf ./Downloads/jetbrains-toolbox-2.5.2.35332.tar.gz -C /opt or into $HOME/.local/share/ ``` -------------------------------- ### Run Chatbot Example Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/chatbots/page.adoc Commands to launch the interactive shell and perform ingestion and chat tasks. ```bash ./scripts/shell.sh # In the shell: ingest ./data/document.md chat > What does the document say about... ``` -------------------------------- ### Run Zipkin Locally Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-observability/README.md Start a Zipkin server using Docker for local testing and development. ```bash docker run -d -p 9411:9411 openzipkin/zipkin ``` -------------------------------- ### Java Utility AI Action Example Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/planners/page.adoc Example of a Java component using @EmbabelComponent to define actions for Utility AI. It shows how to bind outputs and define preconditions for actions. ```java @EmbabelComponent // <1> public class IssueActions { private final ShepherdProperties properties; private final CommunityDataManager communityDataManager; private final GitHubUpdater gitHubUpdater; public IssueActions(ShepherdProperties properties, CommunityDataManager communityDataManager, GitHubUpdater gitHubUpdater) { this.properties = properties; this.communityDataManager = communityDataManager; this.gitHubUpdater = gitHubUpdater; } @Action(outputBinding = "ghIssue") // <2> public GHIssue saveNewIssue(GHIssue ghIssue, OperationContext context) { var existing = communityDataManager.findIssueByGithubId(ghIssue.getId()); if (existing == null) { var issueEntityStatus = communityDataManager.saveAndExpandIssue(ghIssue); context.add(issueEntityStatus); // <3> return ghIssue; } return null; // <4> } @Action( pre = {"spel:newEntity.newEntities.?[#this instanceof T(com.embabel.shepherd.domain.Issue)].size() > 0"} // <5> ) public IssueAssessment reactToNewIssue(GHIssue ghIssue, NewEntity newEntity, Ai ai) { return ai .withLlm(properties.getTriageLlm()) .creating(IssueAssessment.class) .fromTemplate("first_issue_response", Map.of("issue", ghIssue)); // <6> } @Action(pre = {"spel:issueAssessment.urgency > 0.0"}) // <7> public void heavyHitterIssue(GHIssue issue, IssueAssessment issueAssessment) { // Take action on high-urgency issues } } ``` -------------------------------- ### LM Studio Configuration Example Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/getting-started/installing/page.adoc Configure Embabel Agent to use LM Studio with a local OpenAI-compatible API server. ```yaml embabel: agent: platform: autonomy: agent-confidence-cut-off: 0.8 goal-confidence-cut-off: 0.8 models: lmstudio: base-url: http://127.0.0.1:1234 models: default-llm: openai/gpt-oss-20b default-embedding-model: text-embedding-nomic-embed-text-v1.5 ``` -------------------------------- ### Initial State and Available Tools Example Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/planners/page.adoc Illustrates the initial state of the blackboard and the tools available to the LLM before any parameters are curried out. ```text # Initial state: empty blackboard Available tools: - gatherMarketData(request: MarketDataRequest) -> MarketData - analyzeCompetitors(request: CompetitorAnalysisRequest) -> CompetitorAnalysis ``` -------------------------------- ### Verify Ollama Server and Model Installation Source: https://github.com/embabel/embabel-agent/wiki/Troubleshooting Check if the Ollama server is running and accessible, and verify that the desired models are installed. If not, start the server or pull the model. ```bash # Check if Ollama is running curl http://localhost:11434/api/tags # Should return JSON with your models # If not, start Ollama: ollama serve ``` ```bash # List installed models ollama list # Pull a model if none exist ollama pull llama3.2:1b ``` -------------------------------- ### Example shell commands Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/getting-started/running/page.adoc Common commands for testing horoscope agents, web research, and fact-checking capabilities. ```text # Simple horoscope agent execute "My name is Sarah and I'm a Leo" # Research with web tools (requires Docker Desktop with MCP extension) execute "research the recent australian federal election. what is the position of the Greens party?" # Fact checking x "fact check the following: holden cars are still made in australia" ``` -------------------------------- ### Interactive Chat Session Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-starters/embabel-agent-starter-shell/README.md Example of starting and interacting with a chat session within the shell. ```bash shell:> chat Chat session abc123 started. Type 'exit' to end the session. Type /help for available commands. You: Hello! Assistant: Hi there! How can I help you today? You: exit Conversation finished ``` -------------------------------- ### Create Simple Framework-Agnostic Tool (Java) Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/tools/page.adoc Demonstrates creating a simple, framework-agnostic 'greet' tool using the Tool.create() factory method. The tool takes no input and returns a text result. ```java Tool greetTool = Tool.create( "greet", "Greets the user", (input) -> Tool.Result.text("Hello!") ); ``` -------------------------------- ### Development Environment Configuration Template Source: https://github.com/embabel/embabel-agent/wiki/Profiles-Migration-(Completed) Example YAML configuration for the development environment. This template should be copied and customized for local development setups. ```yaml # Copy to your src/main/resources/application.yml.unused and customize embabel: agent: platform: test: mockMode: true agent: logging: personality: starwars verbosity: debug infrastructure: neo4j: enabled: true uri: bolt://localhost:7687 authentication: username: ${NEO4J_USERNAME:} password: ${NEO4J_PASSWORD:} shell: enabled: true chat: confirmGoals: true ``` -------------------------------- ### ArtifactSinkingTool Example (Java) Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/tools/page.adoc Shows how to wrap a tool with `Tool.publishToBlackboard` to capture artifacts from its results and publish them to the blackboard. This is foundational for making structured outputs available. ```java // Capture all artifacts and publish to blackboard Tool wrapped = Tool.publishToBlackboard(myTool); ``` -------------------------------- ### Run Embabel Agent with Shell Profile Source: https://github.com/embabel/embabel-agent/wiki/Quick-Start-Guide Start the Embabel agent using the Spring Boot Maven plugin with the 'shell' profile enabled for interactive use. Example commands are provided. ```bash # Start the interactive shell mvn spring-boot:run -Dspring-boot.run.profiles=shell # Try these commands: help execute "Lynda is a Scorpio, find news for her" -p -r chat ``` -------------------------------- ### Self Unsticking Agent Implementation in Java Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/annotations/page.adoc Provides an example of an agent implementing the `StuckHandler` interface to manage situations where an action gets stuck. The `handleStuck` method is invoked when an agent is unable to proceed. ```java @Agent(description = "self unsticking agent") public class SelfUnstickingAgent implements StuckHandler { private boolean called = false; // The agent will get stuck as there's no dog to convert to a frog @Action @AchievesGoal(description = "the big goal in the sky") public Frog toFrog(Dog dog) { return new Frog(dog.name()); } // This method will be called when the agent is stuck @Override public StuckHandlerResult handleStuck(AgentProcess agentProcess) { ``` -------------------------------- ### Using CreationExample with withExample() Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/testing/page.adoc Demonstrates how to use a `CreationExample` data class with the `withExample` method for a single test case. This is useful for providing specific input-output pairs for testing. ```kotlin import io.mockk.every import io.mockk.mockk import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertDoesNotThrow import org.junit.jupiter.api.assertThrows import org.embabel.core.context.FakeOperationContext import org.embabel.core.model.CreationExample import org.embabel.core.model.creation.ChannelEditPlan import kotlin.test.assertEquals internal class CreationExampleTest { @Test fun `should use CreationExample data class`() { val context = FakeOperationContext.create() val expectedPlan = ChannelEditPlan(1, "Lead Vox") context.expectResponse(expectedPlan) // Create a reusable example using CreationExample val example = CreationExample( description = "Rename channel example", value = ChannelEditPlan(2, "Rhythm") ) val result = context.ai() .withDefaultLlm() .creating(ChannelEditPlan::class.java) .withExample(example) // Pass the CreationExample directly .fromPrompt("Analyze the edit request") assertEquals(expectedPlan, result) } } ``` -------------------------------- ### Java Supervisor Agent Example Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/planners/page.adoc Demonstrates how to configure a Java agent to use the Supervisor planner and define actions with typed inputs and outputs. ```java @Agent( planner = PlannerType.SUPERVISOR, description = "Market research report generator" ) public class MarketResearchAgent { public record MarketDataRequest(String topic) {} public record MarketData(Map revenues, Map marketShare) {} public record CompetitorAnalysisRequest(List companies) {} public record CompetitorAnalysis(Map> strengths) {} public record ReportRequest(String topic, List companies) {} public record FinalReport(String title, List sections) {} @Action(description = "Gather market data including revenues and market share") // <1> public MarketData gatherMarketData(MarketDataRequest request, Ai ai) { return ai.withDefaultLlm().createObject( "Generate market data for: " + request.topic(), MarketData.class ); } @Action(description = "Analyze competitors: strengths and positioning") public CompetitorAnalysis analyzeCompetitors(CompetitorAnalysisRequest request, Ai ai) { return ai.withDefaultLlm().createObject( "Analyze competitors: " + String.join(", ", request.companies()), CompetitorAnalysis.class ); } ``` -------------------------------- ### Install Docling Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/README.md Installs the Docling Python package, a tool for converting documentation formats. ```bash pip install docling ``` -------------------------------- ### Install Java 21 on Ubuntu Source: https://github.com/embabel/embabel-agent/wiki/Development-Environment-Setup-‐-Linux Downloads and installs the Oracle JDK 21 Debian package. ```bash wget https://download.oracle.com/java/21/latest/jdk-21_linux-x64_bin.deb sudo apt install ./Downloads/jdk-21_linux-x64_bin.deb java --version ``` -------------------------------- ### Shell Command for Horoscope Example Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/guides/horoscope/page.adoc Execute this shell command to trigger the Horoscope Example and observe the interaction. ```shell sc tenantId=acme x "Natasha is Pisces. Find news for her" -d ``` -------------------------------- ### Adding Multiple Examples with withExamples() from a List (Kotlin) Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/testing/page.adoc Demonstrates using `withExamples` with a Kotlin list for providing multiple test cases. This mirrors the Java functionality for Kotlin developers. ```kotlin import org.junit.jupiter.api.Test import org.embabel.core.context.FakeOperationContext import org.embabel.core.model.CreationExample import org.embabel.core.model.creation.ChannelEditPlan import kotlin.test.assertEquals import kotlin.test.assertTrue internal class CreationExampleTest { @Test fun `should add multiple examples from list`() { val context = FakeOperationContext.create() val expectedPlan = ChannelEditPlan(1, "Lead Vox") context.expectResponse(expectedPlan) // Create a list of examples (could be loaded from configuration) val examples = listOf( CreationExample("Rename to Bass", ChannelEditPlan(1, "Bass")), CreationExample("Rename to Drums", ChannelEditPlan(2, "Drums")), CreationExample("Rename to Keys", ChannelEditPlan(3, "Keys")), CreationExample("Rename to Vocals", ChannelEditPlan(4, "Vocals")) ) val result = context.ai() .withDefaultLlm() .creating(ChannelEditPlan::class.java) .withExamples(examples) // Pass all examples at once .fromPrompt("Analyze the request") assertEquals(expectedPlan, result) // Verify all examples were added val promptContributors = context.llmInvocations.first().interaction.promptContributors assertTrue(promptContributors.size >= 4) } } ``` -------------------------------- ### File Operations Tools Example Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/tools/page.adoc Example of defining file operation tools categorized for read and write operations. ```APIDOC ## FileTools (Java) ### Description Provides file operation tools categorized into 'read' and 'write' operations. ### Class Annotation @UnfoldingTools( name = "file_operations", description = "File operations. Pass category: 'read' or 'write'." ) ### Methods #### readFile @LlmTool(description = "Read file contents", category = "read") public String readFile(String path) #### listDir @LlmTool(description = "List directory contents", category = "read") public List listDir(String path) #### writeFile @LlmTool(description = "Write file contents", category = "write") public void writeFile(String path, String content) #### deleteFile @LlmTool(description = "Delete a file", category = "write") public void deleteFile(String path) ## FileTools (Kotlin) ### Description Provides file operation tools categorized into 'read' and 'write' operations. ### Class Annotation @UnfoldingTools( name = "file_operations", description = "File operations. Pass category: 'read' or 'write'." ) ### Methods #### readFile @LlmTool(description = "Read file contents", category = "read") fun readFile(path: String): String #### listDir @LlmTool(description = "List directory contents", category = "read") fun listDir(path: String): List #### writeFile @LlmTool(description = "Write file contents", category = "write") fun writeFile(path: String, content: String) #### deleteFile @LlmTool(description = "Delete a file", category = "write") fun deleteFile(path: String) ``` -------------------------------- ### RunSubagent Examples Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/annotations/page.adoc Examples of using RunSubagent to delegate to a subagent. Use fromAnnotatedInstance when you have an @Agent-annotated instance, and instance when you have an Agent object. ```java RunSubagent.fromAnnotatedInstance(new SubAgent(), Result.class) ``` ```java RunSubagent.instance(agent, Result.class) ``` ```java context.asSubProcess(Result.class, agent) ``` -------------------------------- ### Development and Production App Configuration Source: https://github.com/embabel/embabel-agent/wiki/Spring-Integration-AutoConfiguration Use `@EnableAgents` for bootstrapping. For development, start with local models. For production, adopt a hybrid approach, adding cloud starters as needed. ```kotlin // Development: Local models only @EnableAgents class DevelopmentApp // Production: Hybrid approach @EnableAgents class ProductionApp // Add cloud starters as needed ``` -------------------------------- ### Secure Auth Configuration Example Source: https://github.com/embabel/embabel-agent/wiki/Profiles-Migration-(Completed) Demonstrates secure handling of authentication configuration by avoiding hardcoded credentials and mandating environment variable usage for sensitive information. ```kotlin data class AuthConfig( var username: String = "neo4j", var password: String = "defaultpassword" // Security vulnerability! ) data class AuthConfig( var username: String = "", // Must be provided var password: String = "" // Must be provided via environment ) ``` -------------------------------- ### Create Framework-Agnostic Tool with Parameters (Java) Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/tools/page.adoc Shows how to create a framework-agnostic 'add' tool with integer parameters 'a' and 'b' using Tool.create() and InputSchema factory methods. The handler parses input and returns a text result. ```java Tool addTool = Tool.create( "add", "Adds two numbers together", Tool.InputSchema.of( Tool.Parameter.integer("a", "First number"), Tool.Parameter.integer("b", "Second number") ), (input) -> { // Parse input JSON and compute result return Tool.Result.text("42"); } ); ``` -------------------------------- ### Example Zipkin Trace Output Source: https://github.com/embabel/embabel-agent/blob/main/README.md This is an example of how traces appear in Zipkin for an Embabel agent, showing agent lifecycle, actions, and LLM calls. ```text Agent: CustomerServiceAgent ├── Action: AnalyzeRequest │ └── ChatModel: gpt-4 (Spring AI) │ └── tool:searchKnowledgeBase ├── Action: GenerateResponse │ └── ChatModel: gpt-4 (Spring AI) └── status: completed [duration=2340ms] ``` -------------------------------- ### Example Agent Commands Source: https://github.com/embabel/embabel-agent/wiki/Quick-Start-Guide Demonstrates various commands for interacting with Embabel agents, including fact-checking, research (requires web tools), and travel planning. ```bash # Fact checking agent x "fact check: holden cars are still made in australia" # Research agent (requires web tools) execute "research the recent australian federal election" # Travel planning x "plan a 3-day trip to Kyoto for someone interested in temples and food" ``` -------------------------------- ### Music Search Tools Example Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/tools/page.adoc Example of defining music search tools with semantic and text search capabilities, including child tool usage notes. ```APIDOC ## MusicSearchTools (Java) ### Description Defines tools for searching a music database, with specific guidance on using semantic versus text search. ### Class Annotation @UnfoldingTools( name = "music_search", description = "Search music database for artists, albums, and tracks", childToolUsageNotes = "Try vector search first for semantic queries. Use text search for exact artist names." ) ### Methods #### vectorSearch @LlmTool(description = "Semantic search using embeddings") public List vectorSearch(String query) #### textSearch @LlmTool(description = "Exact match text search") public List textSearch(String query) ## MusicSearchTools (Kotlin) ### Description Defines tools for searching a music database, with specific guidance on using semantic versus text search. ### Class Annotation @UnfoldingTools( name = "music_search", description = "Search music database for artists, albums, and tracks", childToolUsageNotes = "Try vector search first for semantic queries. Use text search for exact artist names." ) ### Methods #### vectorSearch @LlmTool(description = "Semantic search using embeddings") fun vectorSearch(query: String): List #### textSearch @LlmTool(description = "Exact match text search") fun textSearch(query: String): List ``` -------------------------------- ### AgentDocument Factory Methods and Example Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/types/page.adoc Methods for creating AgentDocument objects from files, paths, or byte arrays, with support for various document formats and an example of usage. ```APIDOC ## AgentDocument Represents a document for use with document-capable LLMs. ### Factory Methods: - `AgentDocument.fromFile(File)`: Load from file (auto-detects MIME type from common extensions) - `AgentDocument.fromPath(Path)`: Load from path (auto-detects MIME type) - `AgentDocument.create(String, byte[], String?)`: Create with explicit MIME type, byte array, and optional filename - `AgentDocument.fromBytes(String, byte[])`: Create from filename and bytes (auto-detects MIME type) Embabel can identify PDF, CSV, Microsoft Office documents (`.doc`, `.docx`, `.xlsx`), and OpenDocument files (`.odt`, `.ods`, `.odp`) by MIME type. Provider support varies by model and adapter, so verify that the selected LLM can consume the document format you send. If auto-detection fails for a supported document format, use `AgentDocument.create()` with an explicit MIME type. ### Example: [tabs] ==== Java:: + [source,java] ---- var documentPath = java.nio.file.Paths.get("reports/quarterly-report.pdf"); var message = userMessage() .document(documentPath) .build(); var answer = context.ai() .withDefaultLlm() .withMessage(message) .generateText("Summarize this report"); ---- Kotlin:: + [source,kotlin] ---- val documentPath = java.nio.file.Paths.get("reports/quarterly-report.pdf") val document = AgentDocument.fromPath(documentPath) val answer = context.ai() .withDefaultLlm() .withDocument(document) .generateText("Summarize this document") ---- ==== ``` -------------------------------- ### Use CreationExample Data Class (Java) Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/testing/page.adoc Demonstrates using the `CreationExample` data class for defining reusable examples in tests. This snippet is incomplete as it's cut off. ```java import org.junit.jupiter.api.Test; import dev.embabel.api.model.ChannelEditPlan; import dev.embabel.test.FakeOperationContext; import dev.embabel.test.FakePromptRunner.CreationExample; class FakePromptRunnerTest { @Test void shouldUseCreationExampleDataClass() { var context = FakeOperationContext.create(); var expectedPlan = new ChannelEditPlan(1, "Lead Vox"); context.expectResponse(expectedPlan); // Create a reusable example using CreationExample var example = new CreationExample<>( "Rename channel example", new ChannelEditPlan(2, "Rhythm") ); var result = context.ai() .withDefaultLlm() ``` -------------------------------- ### Subagent JSON Input Example Source: https://github.com/embabel/embabel-agent/blob/main/embabel-agent-docs/src/main/asciidoc/reference/tools/page.adoc Example of a JSON object that an LLM might generate to populate the input schema for a Subagent. The structure corresponds to the `WorksToFind` data class. ```json { "composers": ["Mozart", "Beethoven"], "era": "Classical", "maxResults": 5 } ```