This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch CAMEL-26787-chaos-explore
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 1be6bf6ed117bbfed46ff5dc7999d1e64d741ee9
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Nov 9 17:22:28 2026 +0100

    CAMEL-26787: camel-jbang - let there be chaos: the playbook as the MCP 
prompt camel_chaos_explore, and camel cmd chaos-explore with the AI of camel ask
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../org/apache/camel/catalog/docs/chaos.adoc       |   2 +
 components/camel-chaos/src/main/docs/chaos.adoc    |   2 +
 .../modules/ROOT/pages/camel-jbang-managing.adoc   |  17 +-
 .../modules/ROOT/pages/camel-jbang-mcp.adoc        |   8 +
 .../camel-jbang-cmd-chaos-explore.adoc             |  37 ++++
 .../ROOT/pages/jbang-commands/camel-jbang-cmd.adoc |   1 +
 .../META-INF/camel-jbang-commands-metadata.json    |   2 +-
 .../apache/camel/dsl/jbang/core/commands/Ask.java  |   7 +-
 .../dsl/jbang/core/commands/CamelJBangMain.java    |   1 +
 .../dsl/jbang/core/commands/ChaosExplore.java      | 207 +++++++++++++++++++++
 .../core/commands/ai/ChaosExplorePlaybook.java     | 108 +++++++++++
 .../dsl/jbang/core/common/ChaosExperimentRun.java  |   2 +-
 .../dsl/jbang/core/commands/ChaosExploreTest.java  |  83 +++++++++
 .../core/commands/ai/ChaosExplorePlaybookTest.java |  55 ++++++
 .../src/test/resources/golden/cli-help.txt         |  69 +++++++
 .../jbang/core/commands/mcp/PromptDefinitions.java |  22 +++
 .../core/commands/mcp/PromptDefinitionsTest.java   |  16 ++
 17 files changed, 635 insertions(+), 4 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/chaos.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/chaos.adoc
index 66d44391258b..e483e2919166 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/chaos.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/chaos.adoc
@@ -423,6 +423,8 @@ $ camel get chaos --report
 The Camel CLI runs an experiment in one call: `camel cmd chaos-experiment` 
begins it, sends its traffic (`--feed` with
 `--body`, `--repeat` and `--interval`, as `camel cmd send`), waits until its 
expectations are decided (at most
 `--wait`), and ends it. `camel cmd chaos-explore-start` and 
`chaos-explore-finish` start and finish the exploration.
+`camel cmd chaos-explore` hands a whole exploration to an AI: it runs the 
experiments by itself for the budget, and
+reports what held and what broke (the MCP prompt `camel_chaos_explore` is the 
same playbook).
 
 == Scenarios
 
diff --git a/components/camel-chaos/src/main/docs/chaos.adoc 
b/components/camel-chaos/src/main/docs/chaos.adoc
index 66d44391258b..e483e2919166 100644
--- a/components/camel-chaos/src/main/docs/chaos.adoc
+++ b/components/camel-chaos/src/main/docs/chaos.adoc
@@ -423,6 +423,8 @@ $ camel get chaos --report
 The Camel CLI runs an experiment in one call: `camel cmd chaos-experiment` 
begins it, sends its traffic (`--feed` with
 `--body`, `--repeat` and `--interval`, as `camel cmd send`), waits until its 
expectations are decided (at most
 `--wait`), and ends it. `camel cmd chaos-explore-start` and 
`chaos-explore-finish` start and finish the exploration.
+`camel cmd chaos-explore` hands a whole exploration to an AI: it runs the 
experiments by itself for the budget, and
+reports what held and what broke (the MCP prompt `camel_chaos_explore` is the 
same playbook).
 
 == Scenarios
 
diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-managing.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-jbang-managing.adoc
index d41e7b421294..4720ad63b47e 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang-managing.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-managing.adoc
@@ -940,7 +940,22 @@ Experiment 1 FAIL  a failed refund is read again (r1, 
ended after 6s)
 
 The verdict is `FAIL` when an expectation is unmet (exit code 1), `PASS` when 
all are met, and `INCONCLUSIVE` when the
 wait was up before an expectation was decided. `--feed` takes the endpoint, or 
the id of the route, as the `feed:` line
-of `chaos-suggest` has it. `camel get chaos --report` shows the exploration 
with its experiments. See
+of `chaos-suggest` has it. `camel get chaos --report` shows the exploration 
with its experiments.
+
+`camel cmd chaos-explore` lets the AI of `camel ask` do it all: let there be 
chaos. It starts the exploration with the
+budget, and the AI reads the suggestions, runs one experiment per call, reads 
each verdict, and goes on while there is
+time. It asks nothing on the way, as starting the command is the consent, and 
it never changes the routes. When it is
+done the exploration is finished, and its report and the journal of the 
experiments are printed (exit code 1 when an
+experiment failed):
+
+[source,bash]
+----
+camel cmd chaos-explore --budget=10m
+camel cmd chaos-explore myApp --budget=1h --focus=refunds --api-type=anthropic
+----
+
+Run the integration with `--stub=remote`, so the experiments do not reach real 
systems. A route fed over HTTP or from
+files cannot be fed by an experiment yet. MCP clients have the same playbook 
as the prompt `camel_chaos_explore`. See
 xref:next@components:others:chaos.adoc#_an_exploration[An exploration] in the 
camel-chaos documentation.
 
 === Chaos scenarios
diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-mcp.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-jbang-mcp.adoc
index 5b5d95819925..67415f5f6890 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang-mcp.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-mcp.adoc
@@ -1298,4 +1298,12 @@ instructions and executes each step by calling the 
referenced tools.
 | `routeId` (optional), `goal` (optional)
 | Guided workflow to optimize a Camel application's performance: analyze 
throughput, identify bottlenecks,
   review resource usage, and produce prioritized optimization recommendations.
+
+| `camel_chaos_explore`
+| `budget` (optional), `focus` (optional), `name` (optional)
+| Let there be chaos: the AI explores by itself how a running application with 
camel-chaos copes with faults, for the
+  `budget` (10 minutes by default). It starts an exploration, runs one 
experiment per call
+  (`camel_runtime_chaos_experiment`) from the suggestions, reads each verdict, 
and finishes with a report: what held,
+  what broke with the evidence and a hint, and what was not tried. It asks 
nothing on the way and never changes the
+  routes; camel-chaos removes the rules at the deadline. The same playbook as 
`camel cmd chaos-explore`.
 |===
diff --git 
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-cmd-chaos-explore.adoc
 
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-cmd-chaos-explore.adoc
new file mode 100644
index 000000000000..8ddbf5b6a012
--- /dev/null
+++ 
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-cmd-chaos-explore.adoc
@@ -0,0 +1,37 @@
+
+// AUTO-GENERATED by camel-package-maven-plugin - DO NOT EDIT THIS FILE
+= camel cmd chaos-explore
+
+Let there be chaos: an AI explores by itself how a running integration copes 
with faults, for a time budget, and reports what held and what broke
+
+
+== Usage
+
+[source,bash]
+----
+camel cmd chaos-explore [options]
+----
+
+
+
+== Options
+
+[cols="2,5,1,2",options="header"]
+|===
+| Option | Description | Default | Type
+| `--api-key` | API key. Also reads ANTHROPIC_API_KEY, OPENAI_API_KEY, 
WATSONX_APIKEY, or LLM_API_KEY env vars |  | String
+| `--api-type` | API type: 'ollama', 'openai', 'anthropic', or 'watsonx' |  | 
ApiType
+| `--budget` | How long the AI explores, between 10s and 2h | 10m | String
+| `--focus` | What to explore, such as a route id (default: all routes) |  | 
String
+| `--max-iterations` | Maximum number of tool-calling rounds | 100 | int
+| `--model` | Model to use. Default: the provider's default; with Ollama the 
installed model best at tool calling |  | String
+| `--show-tools` | Show the tool calls and results as they happen |  | boolean
+| `--timeout` | Timeout in seconds for one answer of the LLM (an experiment 
can take minutes) | 300 | int
+| `--tools` | The tools the model gets: core (a small set, for a local model), 
full, or auto | auto | ToolSet
+| `--url` | LLM API endpoint URL, as for camel ask. Auto-detected if not 
specified |  | String
+| `--verbose` | Print debug information of the LLM calls |  | boolean
+| `--yes` | Let the AI send messages to endpoints the integration does not 
have, and run the other calls that camel ask asks for first, without asking |  
| boolean
+| `-h,--help` | Display the help and sub-commands |  | boolean
+|===
+
+
diff --git 
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-cmd.adoc 
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-cmd.adoc
index 1c4a85c0047e..6d3b52059917 100644
--- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-cmd.adoc
+++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-cmd.adoc
@@ -23,6 +23,7 @@ camel cmd [options]
 | xref:jbang-commands/camel-jbang-cmd-chaos-change.adoc[chaos-change] | Change 
a chaos rule of a running integration (camel-chaos, for development only)
 | xref:jbang-commands/camel-jbang-cmd-chaos-clear.adoc[chaos-clear] | Remove 
all chaos rules of running integrations (camel-chaos, for development only)
 | xref:jbang-commands/camel-jbang-cmd-chaos-experiment.adoc[chaos-experiment] 
| Run one chaos experiment in the exploration of a running integration: add its 
rules, send its traffic, wait for the verdict, and end it
+| xref:jbang-commands/camel-jbang-cmd-chaos-explore.adoc[chaos-explore] | Let 
there be chaos: an AI explores by itself how a running integration copes with 
faults, for a time budget, and reports what held and what broke
 | 
xref:jbang-commands/camel-jbang-cmd-chaos-explore-finish.adoc[chaos-explore-finish]
 | Finish the chaos exploration of a running integration before its deadline
 | 
xref:jbang-commands/camel-jbang-cmd-chaos-explore-start.adoc[chaos-explore-start]
 | Start a chaos exploration in a running integration: a time to try chaos 
rules in, that camel-chaos enforces
 | xref:jbang-commands/camel-jbang-cmd-chaos-load.adoc[chaos-load] | Load a 
chaos scenario into a running integration (camel-chaos, for development only)
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
 
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
index ccde7b460870..b7bba9ca7fc9 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
@@ -3,7 +3,7 @@
     { "name": "ask", "fullName": "ask", "description": "Ask a question about a 
running Camel application using AI", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.Ask", "options": [ { "names": 
"--api-key", "description": "API key. Also reads ANTHROPIC_API_KEY, 
OPENAI_API_KEY, WATSONX_APIKEY, or LLM_API_KEY env vars", "javaType": 
"java.lang.String", "type": "string" }, { "names": "--api-type", "description": 
"API type: 'ollama', 'openai', 'anthropic', or 'watsonx'", "javaType":  [...]
     { "name": "bind", "fullName": "bind", "description": "DEPRECATED: Bind 
source and sink Kamelets as a new Camel integration", "deprecated": true, 
"sourceClass": "org.apache.camel.dsl.jbang.core.commands.bind.Bind", "options": 
[ { "names": "--error-handler", "description": "Add error handler 
(none|log|sink:<endpoint>). Sink endpoints are expected in the format 
\"[[apigroup\/]version:]kind:[namespace\/]name\", plain Camel URIs or Kamelet 
name.", "javaType": "java.lang.String", "type": " [...]
     { "name": "catalog", "fullName": "catalog", "description": "List artifacts 
from Camel Catalog", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.catalog.CatalogCommand", "options": [ 
{ "names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": 
"component", "fullName": "catalog component", "description": "List components 
from the Camel Catalog", "sourceClass": "org.apache.camel.dsl.jbang.co [...]
-    { "name": "cmd", "fullName": "cmd", "description": "Performs commands in 
the running Camel integrations, such as start\/stop route, or change logging 
levels.", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.action.CamelAction", "options": [ { 
"names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": 
"browse", "fullName": "cmd browse", "description": "Browse pending messages on 
endpoints [...]
+    { "name": "cmd", "fullName": "cmd", "description": "Performs commands in 
the running Camel integrations, such as start\/stop route, or change logging 
levels.", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.action.CamelAction", "options": [ { 
"names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": 
"browse", "fullName": "cmd browse", "description": "Browse pending messages on 
endpoints [...]
     { "name": "completion", "fullName": "completion", "description": "Generate 
completion script for bash\/zsh", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.Complete", "options": [ { "names": 
"-h,--help", "description": "Display the help and sub-commands", "javaType": 
"boolean", "type": "boolean" } ] },
     { "name": "config", "fullName": "config", "description": "Get and set user 
configuration values", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.config.ConfigCommand", "options": [ { 
"names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "get", 
"fullName": "config get", "description": "Display user configuration value", 
"sourceClass": "org.apache.camel.dsl.jbang.core.commands.config. [...]
     { "name": "debug", "fullName": "debug", "description": "Debug local Camel 
integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Debug", 
"options": [ { "names": "--ago", "description": "Use ago instead of yyyy-MM-dd 
HH:mm:ss in timestamp.", "javaType": "boolean", "type": "boolean" }, { "names": 
"--background", "description": "Run in the background", "defaultValue": 
"false", "javaType": "boolean", "type": "boolean" }, { "names": 
"--background-wait", "description": "How [...]
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Ask.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Ask.java
index c3a78931d857..dbdccd7ca25b 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Ask.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Ask.java
@@ -21,6 +21,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Locale;
+import java.util.Set;
 import java.util.function.Function;
 
 import org.apache.camel.dsl.jbang.core.commands.ai.AnswerChecks;
@@ -128,6 +129,9 @@ public class Ask extends CamelCommand {
     /** Below this size (billions of parameters) a model's answers about a 
running integration are often wrong. */
     static final double SMALL_MODEL_BILLIONS = 8;
 
+    // the tools the model does not get, such as starting a chaos exploration 
that camel cmd chaos-explore started
+    Set<String> hiddenTools = Set.of();
+
     private long targetPid;
     private AskTools askTools;
     // the chat's reader, or one made on the terminal for the first call to 
confirm
@@ -182,7 +186,8 @@ public class Ask extends CamelCommand {
                 process != null ? process.pid() : -1,
                 process != null ? process.name() : null,
                 core, core ? askTools.groupGuidance() : List.of());
-        List<LlmClient.ToolDef> toolDefs = askTools.buildToolDefinitions(core);
+        List<LlmClient.ToolDef> toolDefs = new 
ArrayList<>(askTools.buildToolDefinitions(core));
+        toolDefs.removeIf(t -> hiddenTools.contains(t.name()));
 
         if (question == null || question.isEmpty()) {
             return runInteractiveChat(client, process, systemPrompt, toolDefs);
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
index 89693244f2aa..e768d48e8c5f 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
@@ -263,6 +263,7 @@ public class CamelJBangMain implements Callable<Integer> {
                     .addSubcommand("chaos-change", new CommandLine(new 
CamelChaosChangeAction(this)))
                     .addSubcommand("chaos-clear", new CommandLine(new 
CamelChaosClearAction(this)))
                     .addSubcommand("chaos-experiment", new CommandLine(new 
CamelChaosExperimentAction(this)))
+                    .addSubcommand("chaos-explore", new CommandLine(new 
ChaosExplore(this)))
                     .addSubcommand("chaos-explore-finish", new CommandLine(new 
CamelChaosExploreFinishAction(this)))
                     .addSubcommand("chaos-explore-start", new CommandLine(new 
CamelChaosExploreStartAction(this)))
                     .addSubcommand("chaos-load", new CommandLine(new 
CamelChaosLoadAction(this)))
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ChaosExplore.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ChaosExplore.java
new file mode 100644
index 000000000000..5800dded6098
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ChaosExplore.java
@@ -0,0 +1,207 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.jbang.core.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.camel.dsl.jbang.core.commands.ai.ChaosExplorePlaybook;
+import org.apache.camel.dsl.jbang.core.commands.process.ListChaos;
+import org.apache.camel.dsl.jbang.core.common.ActionClient;
+import org.apache.camel.dsl.jbang.core.common.ActionClient.ActionResult;
+import org.apache.camel.dsl.jbang.core.common.ChaosExperimentRun;
+import org.apache.camel.dsl.jbang.core.common.CliExitCode;
+import org.apache.camel.dsl.jbang.core.common.ProcessFinder;
+import org.apache.camel.dsl.jbang.core.common.ProcessFinder.CamelProcess;
+import org.apache.camel.dsl.jbang.core.common.RuntimeHelper;
+import org.apache.camel.util.TimeUtils;
+import org.apache.camel.util.json.JsonObject;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
+import picocli.CommandLine.Parameters;
+
+/**
+ * Let there be chaos (CAMEL-26787): the AI of camel ask explores chaos on a 
running integration by itself, for the
+ * budget of the user, and reports at the end.
+ */
+@Command(name = "chaos-explore",
+         description = "Let there be chaos: an AI explores by itself how a 
running integration copes with faults, for a"
+                       + " time budget, and reports what held and what broke",
+         sortOptions = false, showDefaultValues = true,
+         footer = {
+                 "%nThis command starts a chaos exploration with the budget 
(camel cmd chaos-explore-start), and hands",
+                 "it to the AI of camel ask with a playbook: read the 
suggestions, run one experiment per call",
+                 "(camel cmd chaos-experiment), read the verdicts, and go on 
while there is time. The AI asks",
+                 "nothing on the way: starting this command is the consent to 
the exploration, and camel-chaos",
+                 "removes every rule at the deadline. The AI never changes the 
routes. When it is done, the",
+                 "exploration is finished, and its report and the journal of 
the experiments are printed. The exit",
+                 "code is 1 when an experiment failed.",
+                 "%nThe integration needs camel-chaos switched on (camel run 
--chaos), and remote endpoints are best",
+                 "stubbed (camel run --stub=remote), so the experiments do not 
reach real systems.",
+                 "%nExamples:",
+                 "  camel cmd chaos-explore",
+                 "  camel cmd chaos-explore myApp --budget=30m 
--focus=refunds",
+                 "  camel cmd chaos-explore --api-type=anthropic --budget=1h" 
})
+public class ChaosExplore extends CamelCommand {
+
+    @Parameters(description = "Name or pid of the running Camel integration 
(must match one); without it, the only one"
+                              + " running, or the only one with chaos switched 
on",
+                arity = "0..1")
+    String name;
+
+    @Option(names = { "--budget" }, defaultValue = "10m",
+            description = "How long the AI explores, between 10s and 2h")
+    String budget;
+
+    @Option(names = { "--focus" },
+            description = "What to explore, such as a route id (default: all 
routes)")
+    String focus;
+
+    @Option(names = { "--url" },
+            description = "LLM API endpoint URL, as for camel ask. 
Auto-detected if not specified")
+    String url;
+
+    @Option(names = { "--api-type" },
+            description = "API type: 'ollama', 'openai', 'anthropic', or 
'watsonx'")
+    LlmClient.ApiType apiType;
+
+    @Option(names = { "--api-key" },
+            description = "API key. Also reads ANTHROPIC_API_KEY, 
OPENAI_API_KEY, WATSONX_APIKEY, or LLM_API_KEY env vars")
+    String apiKey;
+
+    @Option(names = { "--model" },
+            description = "Model to use. Default: the provider's default; with 
Ollama the installed model best at"
+                          + " tool calling")
+    String model;
+
+    @Option(names = { "--timeout" }, defaultValue = "300",
+            description = "Timeout in seconds for one answer of the LLM (an 
experiment can take minutes)")
+    int timeout = 300;
+
+    @Option(names = { "--max-iterations" }, defaultValue = "100",
+            description = "Maximum number of tool-calling rounds")
+    int maxIterations = 100;
+
+    @Option(names = { "--tools" }, defaultValue = "auto",
+            description = "The tools the model gets: core (a small set, for a 
local model), full, or auto")
+    Ask.ToolSet tools = Ask.ToolSet.auto;
+
+    @Option(names = { "--yes" },
+            description = "Let the AI send messages to endpoints the 
integration does not have, and run the other calls"
+                          + " that camel ask asks for first, without asking")
+    boolean yes;
+
+    @Option(names = { "--show-tools" },
+            description = "Show the tool calls and results as they happen")
+    boolean showTools;
+
+    @Option(names = { "--verbose" },
+            description = "Print debug information of the LLM calls")
+    boolean verbose;
+
+    public ChaosExplore(CamelJBangMain main) {
+        super(main);
+    }
+
+    @Override
+    public Integer doCall() throws Exception {
+        CamelProcess process = ProcessFinder.requireOneForChaos(name);
+        // the exploration has the budget of the user, not one the AI picks
+        ActionResult started = ActionClient.execute(process, "chaos", root -> {
+            root.put("command", "explore-start");
+            root.put("budget", budget);
+            if (focus != null && !focus.isBlank()) {
+                root.put("focus", focus);
+            }
+        }, 10000);
+        if (!started.isOk()) {
+            printer().printErr(started.error());
+            return started.exitCode();
+        }
+        printer().println("Let there be chaos: " + process.name() + " (pid " + 
process.pid() + "), "
+                          + 
TimeUtils.printDuration(started.reply().getLongOrDefault("budget", 0))
+                          + (focus != null && !focus.isBlank() ? ", focus: " + 
focus : ""));
+        int answer;
+        try {
+            answer = ask(process).doCall();
+        } finally {
+            // the AI may have finished it already; else its rules go now
+            ActionClient.execute(process, "chaos", root -> root.put("command", 
"explore-finish"), 10000);
+        }
+        JsonObject exploration = 
ChaosExperimentRun.exploration(RuntimeHelper.readStatus(process.pid()));
+        List<String> lines = journal(exploration);
+        printer().println();
+        lines.forEach(printer()::println);
+        if (failed(exploration)) {
+            return CliExitCode.FAILURE;
+        }
+        return answer;
+    }
+
+    /** camel ask, with the playbook as its question, for the integration. */
+    Ask ask(CamelProcess process) {
+        Ask ask = new Ask(getMain());
+        ask.question = 
List.of(ChaosExplorePlaybook.text(ChaosExplorePlaybook.ASK, process.name(), 
budget, focus, true));
+        ask.nameOrPid = Long.toString(process.pid());
+        ask.url = url;
+        ask.apiType = apiType;
+        ask.apiKey = apiKey;
+        ask.model = model;
+        ask.timeout = timeout;
+        ask.maxIterations = maxIterations;
+        ask.tools = tools;
+        ask.yes = yes;
+        ask.showTools = showTools;
+        ask.showStats = true;
+        ask.verbose = verbose;
+        // the exploration runs with the budget of the user: the AI does not 
start another one
+        ask.hiddenTools = Set.of("chaos_explore_start");
+        return ask;
+    }
+
+    /** The journal of the exploration: how it ended, and a line per 
experiment with its expectations. */
+    static List<String> journal(JsonObject exploration) {
+        List<String> lines = new ArrayList<>();
+        if (exploration == null) {
+            lines.add("No journal of the exploration in the status of the 
integration");
+            return lines;
+        }
+        List<Object> experiments = exploration.getCollection("experiments");
+        int count = experiments != null ? experiments.size() : 0;
+        long failed = experiments == null
+                ? 0 : experiments.stream()
+                        .filter(o -> o instanceof JsonObject jo && 
"FAIL".equals(jo.getString("verdict"))).count();
+        long ran = exploration.getLongOrDefault("finishedAt", 0) - 
exploration.getLongOrDefault("startedAt", 0);
+        lines.add("Chaos exploration " + 
("deadline".equals(exploration.getString("finishedBy"))
+                ? "finished at its deadline" : "finished")
+                  + (ran > 0 ? " after " + TimeUtils.printDuration(ran) : "") 
+ ": " + count
+                  + (count == 1 ? " experiment" : " experiments") + ", " + 
failed + " failed");
+        if (experiments != null) {
+            for (Object o : experiments) {
+                lines.addAll(ListChaos.experimentLines((JsonObject) o, "  "));
+            }
+        }
+        return lines;
+    }
+
+    private static boolean failed(JsonObject exploration) {
+        List<Object> experiments = exploration != null ? 
exploration.getCollection("experiments") : null;
+        return experiments != null
+                && experiments.stream().anyMatch(o -> o instanceof JsonObject 
jo && "FAIL".equals(jo.getString("verdict")));
+    }
+}
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/ChaosExplorePlaybook.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/ChaosExplorePlaybook.java
new file mode 100644
index 000000000000..33a80209ac75
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/ChaosExplorePlaybook.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.jbang.core.commands.ai;
+
+/**
+ * The playbook of "let there be chaos" (CAMEL-26787): what an AI does to 
explore chaos on an integration by itself, for
+ * the time of an exploration, and the report it comes back with. One text for 
the MCP prompt
+ * {@code camel_chaos_explore} and for {@code camel cmd chaos-explore} (the AI 
of camel ask), each with the names of its
+ * own tools.
+ * <p/>
+ * The AI steers on its own and asks the user nothing: the user agreed to the 
exploration, camel-chaos removes its rules
+ * at the deadline, and the AI never changes the routes. One experiment per 
call keeps it to about ten calls in ten
+ * minutes, which a small local model can do.
+ */
+public final class ChaosExplorePlaybook {
+
+    /** The names of the tools the playbook tells the AI to call. */
+    public record Tools(String start, String report, String suggest, String 
experiment, String finish, String errors) {
+    }
+
+    /** The tools of the MCP server. */
+    public static final Tools MCP = new Tools(
+            "camel_runtime_chaos_explore_start", "camel_runtime_chaos_report", 
"camel_runtime_chaos_suggest",
+            "camel_runtime_chaos_experiment", 
"camel_runtime_chaos_explore_finish", "camel_get_errors");
+
+    /** The tools of camel ask. */
+    public static final Tools ASK = new Tools(
+            "chaos_explore_start", "chaos_report", "chaos_suggest", 
"chaos_experiment", "chaos_explore_finish",
+            "get_errors");
+
+    private ChaosExplorePlaybook() {
+    }
+
+    /**
+     * The playbook.
+     *
+     * @param tools       the names of the tools
+     * @param integration the name of the integration, or null for the one the 
tools select
+     * @param budget      how long the exploration runs, such as 10m (10m when 
null)
+     * @param focus       what to explore, such as a route, or null for all 
routes
+     * @param started     whether the exploration is already running (camel 
cmd chaos-explore starts it with the budget
+     *                    of the user), else the AI starts it
+     */
+    public static String text(Tools tools, String integration, String budget, 
String focus, boolean started) {
+        String where = integration != null && !integration.isBlank()
+                ? "the integration " + integration.strip()
+                : "the running integration";
+        String time = budget != null && !budget.isBlank() ? budget.strip() : 
"10m";
+        String about = focus != null && !focus.isBlank()
+                ? "Focus on " + focus.strip() + ", and the routes it hands 
messages to."
+                : "Explore all routes, the most worth trying first.";
+        String start = started
+                ? "The exploration is running (" + time + "): do not start 
another one."
+                : "Start the exploration with " + tools.start() + " (budget " 
+ time + ").";
+        return """
+                Let there be chaos: explore how %s copes with faults, by 
yourself, for %s. %s
+                camel-chaos adds the faults and removes every rule at the 
deadline of the exploration. Do not ask \
+                the user anything, and never change the routes or files: try, 
measure, and report at the end.
+
+                1. %s Then read %s: the routes and their counts before chaos 
(the baseline), and what was tried.
+                2. Call %s for ideas: rules per route with why, and the feed 
of each route (how messages get in). \
+                Prefer the kinds not tried yet; single faults first, then the 
combined ones (two faults at once).
+                3. Run one experiment per idea with %s. A rule makes exchanges 
fail or wait on purpose, so do not \
+                expect that nothing fails where the fault is: expect what 
should hold despite it, such as nothing \
+                lost after a hand-off to another route, a failure handled by 
the error handler or redelivered, or the \
+                route still completing its messages in time.
+                   - hypothesis: what should hold, in a few words, such as "a 
failed refund is retried, not lost"
+                   - rule: the suggested rule with a short until= (such as 
until=30s), and one expectation that \
+                decides the hypothesis, with within= a little longer than 
until=: expect=<route>:failed<=0 \
+                (nothing fails), expect=<route>-><next route>:lost<=0 (nothing 
lost between two routes), \
+                expect=<route>:20 (20 completed), expect=<route>:maxTime<=5s 
(none slower than 5s)
+                   - feed: when the feed of the suggestion is kind send, its 
endpoint, with body, repeat (such as \
+                20) and interval (such as 100..300); leave feed out when the 
route feeds itself (kind self). \
+                Routes fed over http or from files cannot be fed by an 
experiment yet: try them only when they \
+                feed themselves
+                   - wait: longer than the within= of the expectation
+                   - note: what you make of the result, in one sentence
+                4. Read the result: the verdict (FAIL, PASS or INCONCLUSIVE), 
the expectations, what the routes \
+                did, and the traffic. On FAIL, call %s for the failed 
exchanges and their exceptions, and say why it \
+                broke. On INCONCLUSIVE, run it again with a longer wait. On 
PASS, move on.
+                5. Go on while timeLeft of the result is more than the next 
experiment needs (its until= and wait, \
+                plus a minute). Stop with about a minute left.
+                6. Finish with %s, and write the report:
+                   - Summary: how many experiments, how many held and how many 
broke
+                   - Findings: per FAIL the route, what broke, the evidence 
(the expectation and its actual value, \
+                the exception), and a hint for the route in terms of its error 
handling (a dead letter channel, \
+                redelivery, onException, a circuit breaker, idempotency), not 
endpoint options you are not sure \
+                exist; say when it looks like a bug in Camel rather than in 
the route
+                   - What held: one line per PASS
+                   - Not tried: the kinds of fault or routes left out, and why 
(no feed, out of time)
+                """.formatted(where, time, about, start, tools.report(), 
tools.suggest(), tools.experiment(),
+                tools.errors(), tools.finish());
+    }
+}
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/ChaosExperimentRun.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/ChaosExperimentRun.java
index 40b0a5a1b751..742c29a7c6dc 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/ChaosExperimentRun.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/ChaosExperimentRun.java
@@ -235,7 +235,7 @@ public final class ChaosExperimentRun {
     }
 
     /** The exploration in the report of the chaos console in the status, or 
null. */
-    static JsonObject exploration(JsonObject status) {
+    public static JsonObject exploration(JsonObject status) {
         if (status == null || !(status.get("chaos") instanceof JsonObject 
chaos)
                 || !(chaos.get("report") instanceof JsonObject report)) {
             return null;
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ChaosExploreTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ChaosExploreTest.java
new file mode 100644
index 000000000000..fa94b0c72251
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ChaosExploreTest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.jbang.core.commands;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.dsl.jbang.core.common.ProcessFinder.CamelProcess;
+import org.apache.camel.util.json.JsonArray;
+import org.apache.camel.util.json.JsonObject;
+import org.junit.jupiter.api.Test;
+import picocli.CommandLine;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * camel cmd chaos-explore (CAMEL-26787): camel ask gets the playbook and the 
options, and the journal is printed when
+ * the AI is done.
+ */
+class ChaosExploreTest {
+
+    @Test
+    void camelAskGetsThePlaybookAndTheOptions() {
+        ChaosExplore command = new ChaosExplore(new CamelJBangMain());
+        CommandLine.populateCommand(command, "shop", "--budget=30m", 
"--focus=refunds", "--model=qwen3.6",
+                "--api-type=ollama", "--tools=core", "--show-tools");
+
+        Ask ask = command.ask(new CamelProcess(4711, "shop", null));
+
+        assertThat(ask.question).singleElement().asString()
+                .contains("explore how the integration shop copes", "The 
exploration is running (30m)", "chaos_experiment");
+        assertThat(ask.nameOrPid).isEqualTo("4711");
+        assertThat(ask.model).isEqualTo("qwen3.6");
+        assertThat(ask.apiType).isEqualTo(LlmClient.ApiType.ollama);
+        assertThat(ask.tools).isEqualTo(Ask.ToolSet.core);
+        assertThat(ask.showTools).isTrue();
+        // an experiment can take minutes, and a run many rounds
+        assertThat(ask.timeout).isEqualTo(300);
+        assertThat(ask.maxIterations).isEqualTo(100);
+        assertThat(ask.yes).isFalse();
+        // the exploration runs with the budget of the user: the AI does not 
get the tool to start another one
+        assertThat(ask.hiddenTools).containsExactly("chaos_explore_start");
+    }
+
+    @Test
+    void theJournalWhenTheAiIsDone() {
+        JsonObject failed = new JsonObject(
+                Map.of("number", 1, "verdict", "FAIL", "open", false, 
"endedBy", "ended",
+                        "elapsed", 31_000L, "hypothesis", "a refund never 
fails", "rules", new JsonArray(List.of("r1")),
+                        "expectations", new JsonArray(
+                                List.of(new JsonObject(
+                                        Map.of("expect", "refunds:failed<=0", 
"state", "unmet", "value", "4 failed"))))));
+        JsonObject held = new JsonObject(
+                Map.of("number", 2, "verdict", "PASS", "open", false, 
"endedBy", "ended",
+                        "elapsed", 12_000L, "rules", new 
JsonArray(List.of("r2"))));
+        JsonObject exploration = new JsonObject(
+                Map.of("running", false, "finishedBy", "deadline",
+                        "startedAt", 1_000_000L, "finishedAt", 1_180_000L, 
"experiments",
+                        new JsonArray(List.of(failed, held))));
+
+        assertThat(ChaosExplore.journal(exploration)).containsExactly(
+                "Chaos exploration finished at its deadline after 3m0s: 2 
experiments, 1 failed",
+                "  1 FAIL  a refund never fails (r1, ended after 31s)",
+                "    expect refunds:failed<=0: unmet, 4 failed",
+                "  2 PASS (r2, ended after 12s)");
+        assertThat(ChaosExplore.journal(null)).containsExactly(
+                "No journal of the exploration in the status of the 
integration");
+    }
+}
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/ChaosExplorePlaybookTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/ChaosExplorePlaybookTest.java
new file mode 100644
index 000000000000..df3d3d47c071
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/ChaosExplorePlaybookTest.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.jbang.core.commands.ai;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * The playbook of "let there be chaos" (CAMEL-26787): the same steps for 
camel ask and the MCP server, each with the
+ * names of its own tools, which exist.
+ */
+class ChaosExplorePlaybookTest {
+
+    @Test
+    void camelAskGetsItsOwnToolsAndARunningExploration() {
+        String text = ChaosExplorePlaybook.text(ChaosExplorePlaybook.ASK, 
"shop", "30m", "refunds", true);
+
+        assertThat(text).contains("explore how the integration shop copes with 
faults, by yourself, for 30m",
+                "The exploration is running (30m): do not start another one.", 
"Focus on refunds",
+                "chaos_report", "chaos_suggest", "chaos_experiment", 
"chaos_explore_finish", "get_errors")
+                .doesNotContain("camel_runtime_", "chaos_explore_start");
+    }
+
+    @Test
+    void theToolsItNamesExist() {
+        ChaosExplorePlaybook.Tools t = ChaosExplorePlaybook.ASK;
+        for (String name : new String[] { t.start(), t.report(), t.suggest(), 
t.experiment(), t.finish(), t.errors() }) {
+            assertThat(ToolRegistry.findTool(name)).as(name).isNotNull();
+        }
+    }
+
+    @Test
+    void theExpectationsItTeachesAreRulesCamelChaosTakes() {
+        String text = ChaosExplorePlaybook.text(ChaosExplorePlaybook.MCP, 
null, null, null, false);
+
+        // the forms of expect= that ChaosRuleParser reads
+        assertThat(text).contains("expect=<route>:failed<=0", 
"expect=<route>-><next route>:lost<=0",
+                "expect=<route>:20", "expect=<route>:maxTime<=5s", "within=");
+    }
+}
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/cli-help.txt 
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/cli-help.txt
index 2900be01a02a..db328bcb784c 100644
--- a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/cli-help.txt
+++ b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/cli-help.txt
@@ -561,6 +561,9 @@ Commands:
   chaos-experiment      Run one chaos experiment in the exploration of a
                           running integration: add its rules, send its traffic,
                           wait for the verdict, and end it
+  chaos-explore         Let there be chaos: an AI explores by itself how a
+                          running integration copes with faults, for a time
+                          budget, and reports what held and what broke
   chaos-explore-finish  Finish the chaos exploration of a running integration
                           before its deadline
   chaos-explore-start   Start a chaos exploration in a running integration: a
@@ -823,6 +826,72 @@ failed<=0 within=70s' \
       --wait=90s
   camel cmd chaos-experiment --end --note='stopped by hand'
 
+== camel cmd chaos-explore --help
+Usage: camel cmd chaos-explore [-h] [--show-tools] [--verbose] [--yes]
+                               [--api-key=<apiKey>] [--api-type=<apiType>]
+                               [--budget=<budget>] [--focus=<focus>]
+                               [--max-iterations=<maxIterations>]
+                               [--model=<model>] [--timeout=<timeout>]
+                               [--tools=<tools>] [--url=<url>] [<name>]
+Let there be chaos: an AI explores by itself how a running integration copes
+with faults, for a time budget, and reports what held and what broke
+      [<name>]               Name or pid of the running Camel integration (must
+                               match one); without it, the only one running, or
+                               the only one with chaos switched on
+  -h, --help                 Display the help and sub-commands
+      --budget=<budget>      How long the AI explores, between 10s and 2h
+                               Default: 10m
+      --focus=<focus>        What to explore, such as a route id (default: all
+                               routes)
+      --url=<url>            LLM API endpoint URL, as for camel ask.
+                               Auto-detected if not specified
+      --api-type=<apiType>   API type: 'ollama', 'openai', 'anthropic', or
+                               'watsonx'
+      --api-key=<apiKey>     API key. Also reads ANTHROPIC_API_KEY,
+                               OPENAI_API_KEY, WATSONX_APIKEY, or LLM_API_KEY
+                               env vars
+      --model=<model>        Model to use. Default: the provider's default;
+                               with Ollama the installed model best at tool
+                               calling
+      --timeout=<timeout>    Timeout in seconds for one answer of the LLM (an
+                               experiment can take minutes)
+                               Default: 300
+      --max-iterations=<maxIterations>
+                             Maximum number of tool-calling rounds
+                               Default: 100
+      --tools=<tools>        The tools the model gets: core (a small set, for a
+                               local model), full, or auto
+                               Default: auto
+      --yes                  Let the AI send messages to endpoints the
+                               integration does not have, and run the other
+                               calls that camel ask asks for first, without
+                               asking
+      --show-tools           Show the tool calls and results as they happen
+      --verbose              Print debug information of the LLM calls
+
+This command starts a chaos exploration with the budget (camel cmd
+chaos-explore-start), and hands
+it to the AI of camel ask with a playbook: read the suggestions, run one
+experiment per call
+(camel cmd chaos-experiment), read the verdicts, and go on while there is time.
+The AI asks
+nothing on the way: starting this command is the consent to the exploration,
+and camel-chaos
+removes every rule at the deadline. The AI never changes the routes. When it is
+done, the
+exploration is finished, and its report and the journal of the experiments are
+printed. The exit
+code is 1 when an experiment failed.
+
+The integration needs camel-chaos switched on (camel run --chaos), and remote
+endpoints are best
+stubbed (camel run --stub=remote), so the experiments do not reach real 
systems.
+
+Examples:
+  camel cmd chaos-explore
+  camel cmd chaos-explore myApp --budget=30m --focus=refunds
+  camel cmd chaos-explore --api-type=anthropic --budget=1h
+
 == camel cmd chaos-explore-finish --help
 Usage: camel cmd chaos-explore-finish [-h] [--timeout=<timeout>] [<name>]
 Finish the chaos exploration of a running integration before its deadline
diff --git 
a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/PromptDefinitions.java
 
b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/PromptDefinitions.java
index 2cb4a1371637..1cafc11a8f34 100644
--- 
a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/PromptDefinitions.java
+++ 
b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/PromptDefinitions.java
@@ -23,6 +23,7 @@ import jakarta.enterprise.context.ApplicationScoped;
 import io.quarkiverse.mcp.server.Prompt;
 import io.quarkiverse.mcp.server.PromptArg;
 import io.quarkiverse.mcp.server.PromptMessage;
+import org.apache.camel.dsl.jbang.core.commands.ai.ChaosExplorePlaybook;
 
 /**
  * MCP Prompt definitions that provide structured multi-step workflows for 
LLMs.
@@ -382,4 +383,25 @@ public class PromptDefinitions {
 
         return List.of(PromptMessage.withUserRole(instructions));
     }
+
+    /**
+     * Let there be chaos (CAMEL-26787): the AI explores chaos on a running 
integration by itself for a time budget, one
+     * experiment per call, and reports at the end. The playbook is the one of 
camel cmd chaos-explore.
+     */
+    @Prompt(name = "camel_chaos_explore",
+            description = "Let there be chaos: explore by yourself how a 
running Camel application copes with faults, "
+                          + "for a time budget: start a chaos exploration, run 
one experiment per call (rules, traffic "
+                          + "and the wait for the verdict), and report what 
held and what broke, with hints. "
+                          + "Needs camel-chaos switched on (camel run 
--chaos).")
+    public List<PromptMessage> chaosExplore(
+            @PromptArg(name = "budget", description = "How long to explore, 
such as 10m or 1h (default 10m, at most 2h)",
+                       required = false) String budget,
+            @PromptArg(name = "focus", description = "What to explore, such as 
a route id (default: all routes)",
+                       required = false) String focus,
+            @PromptArg(name = "name", description = "Name or PID of the Camel 
application (default: the only one"
+                                                    + " running, or the only 
one with chaos switched on)",
+                       required = false) String name) {
+        return List.of(PromptMessage.withUserRole(
+                ChaosExplorePlaybook.text(ChaosExplorePlaybook.MCP, name, 
budget, focus, false)));
+    }
 }
diff --git 
a/dsl/camel-jbang/camel-jbang-mcp/src/test/java/org/apache/camel/dsl/jbang/core/commands/mcp/PromptDefinitionsTest.java
 
b/dsl/camel-jbang/camel-jbang-mcp/src/test/java/org/apache/camel/dsl/jbang/core/commands/mcp/PromptDefinitionsTest.java
index 5ae648d67beb..79a25fd392e9 100644
--- 
a/dsl/camel-jbang/camel-jbang-mcp/src/test/java/org/apache/camel/dsl/jbang/core/commands/mcp/PromptDefinitionsTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-mcp/src/test/java/org/apache/camel/dsl/jbang/core/commands/mcp/PromptDefinitionsTest.java
@@ -265,6 +265,22 @@ class PromptDefinitionsTest {
         assertThat(mentioned).as("tools named by the 
prompts").isSubsetOf(tools);
     }
 
+    // ---- camel_chaos_explore ----
+
+    @Test
+    void chaosExploreIsThePlaybookWithTheMcpTools() {
+        String text = extractText(prompts.chaosExplore("1h", "refunds", 
"shop"));
+
+        assertThat(text).contains("Let there be chaos: explore how the 
integration shop copes with faults, by"
+                                  + " yourself, for 1h",
+                "Focus on refunds",
+                "Start the exploration with camel_runtime_chaos_explore_start 
(budget 1h)",
+                "camel_runtime_chaos_suggest", 
"camel_runtime_chaos_experiment", "camel_runtime_chaos_explore_finish",
+                "Do not ask the user anything");
+        assertThat(extractText(prompts.chaosExplore(null, null, null)))
+                .contains("the running integration copes with faults, by 
yourself, for 10m", "Explore all routes");
+    }
+
     // ---- helper ----
 
     private String extractText(List<PromptMessage> messages) {

Reply via email to