From e7e0f2d965570cd32af35faafb3557e0d1064cb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20J=C4=99drecki?= Date: Wed, 13 May 2026 15:56:26 +0200 Subject: [PATCH 1/3] Add missing docs to Sphinx --- docs/ai.rst | 158 ++++++++++++++++++++++++++++++ docs/index.rst | 58 ++++++++++- docs/results.rst | 2 + docs/searchcommands.rst | 31 +++--- docs/searchcommandsvalidators.rst | 50 +++++++++- splunklib/ai/agent.py | 8 +- splunklib/ai/security.py | 13 ++- 7 files changed, 289 insertions(+), 31 deletions(-) create mode 100644 docs/ai.rst diff --git a/docs/ai.rst b/docs/ai.rst new file mode 100644 index 000000000..0aeac494d --- /dev/null +++ b/docs/ai.rst @@ -0,0 +1,158 @@ +splunklib.ai +------------ + +.. automodule:: splunklib.ai + +.. autoclass:: splunklib.ai.agent.Agent + :members: invoke, invoke_with_data + +.. autoexception:: splunklib.ai.agent.PrivilegedExecutionError + :members: + +.. rubric:: Models + +.. autoclass:: splunklib.ai.model.PredefinedModel + :members: + +.. autoclass:: splunklib.ai.model.AnthropicModel + :members: + +.. autoclass:: splunklib.ai.model.OpenAIModel + :members: + +.. autoclass:: splunklib.ai.model.GoogleModel + :members: + +.. rubric:: Messages + +.. autoclass:: splunklib.ai.messages.BaseMessage + :members: + +.. autoclass:: splunklib.ai.messages.HumanMessage + :members: + +.. autoclass:: splunklib.ai.messages.AIMessage + :members: + +.. autoclass:: splunklib.ai.messages.SystemMessage + :members: + +.. autoclass:: splunklib.ai.messages.ToolMessage + :members: + +.. autoclass:: splunklib.ai.messages.SubagentMessage + :members: + +.. autoclass:: splunklib.ai.messages.AgentResponse + :members: + +.. autoclass:: splunklib.ai.messages.TextBlock + :members: + +.. autoclass:: splunklib.ai.messages.ToolCall + :members: + +.. autoclass:: splunklib.ai.messages.SubagentCall + :members: + +.. autoclass:: splunklib.ai.messages.ToolResult + :members: + +.. autoclass:: splunklib.ai.messages.SubagentTextResult + :members: + +.. autoclass:: splunklib.ai.messages.SubagentStructuredResult + :members: + +.. autoclass:: splunklib.ai.messages.ToolFailureResult + :members: + +.. autoclass:: splunklib.ai.messages.SubagentFailureResult + :members: + +.. rubric:: Middleware + +.. autoclass:: splunklib.ai.middleware.AgentMiddleware + :members: + +.. autofunction:: splunklib.ai.middleware.agent_middleware + +.. autofunction:: splunklib.ai.middleware.model_middleware + +.. autofunction:: splunklib.ai.middleware.tool_middleware + +.. autofunction:: splunklib.ai.middleware.subagent_middleware + +.. autoclass:: splunklib.ai.middleware.AgentState + :members: + +.. autoclass:: splunklib.ai.middleware.AgentRequest + :members: + +.. autoclass:: splunklib.ai.middleware.ModelRequest + :members: + +.. autoclass:: splunklib.ai.middleware.ModelResponse + :members: + +.. autoclass:: splunklib.ai.middleware.ToolRequest + :members: + +.. autoclass:: splunklib.ai.middleware.ToolResponse + :members: + +.. autoclass:: splunklib.ai.middleware.SubagentRequest + :members: + +.. autoclass:: splunklib.ai.middleware.SubagentResponse + :members: + +.. rubric:: Limits + +.. autoclass:: splunklib.ai.limits.AgentLimits + :members: + +.. autoexception:: splunklib.ai.limits.AgentStopException + :members: + +.. autoexception:: splunklib.ai.limits.TokenLimitExceededException + :members: + +.. autoexception:: splunklib.ai.limits.StepsLimitExceededException + :members: + +.. autoexception:: splunklib.ai.limits.TimeoutExceededException + :members: + +.. autoexception:: splunklib.ai.limits.StructuredOutputRetryLimitExceededException + :members: + +.. rubric:: Tool settings + +.. autoclass:: splunklib.ai.tool_settings.ToolSettings + :members: + +.. autoclass:: splunklib.ai.tool_settings.LocalToolSettings + :members: + +.. autoclass:: splunklib.ai.tool_settings.RemoteToolSettings + :members: + +.. autoclass:: splunklib.ai.tool_settings.ToolAllowlist + :members: + +.. rubric:: Conversation store + +.. autoclass:: splunklib.ai.conversation_store.ConversationStore + :members: + +.. autoclass:: splunklib.ai.conversation_store.InMemoryStore + :members: + +.. rubric:: Security + +.. autofunction:: splunklib.ai.security.detect_injection + +.. autofunction:: splunklib.ai.security.truncate_input + +.. autofunction:: splunklib.ai.security.create_structured_prompt diff --git a/docs/index.rst b/docs/index.rst index 8f209468f..1f2a01997 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -12,6 +12,7 @@ For more information, see the `Splunk Developer Portal /bin/tools.py`). - * Remote tools via `ToolSettings.remote` (requires Splunk MCP Server App present on SH). + loaded and exposed to the model. When provided, the agent loads + local tools via ``ToolSettings.local`` (registered in ``/bin/tools.py``) + and remote tools via ``ToolSettings.remote`` (requires Splunk MCP Server App present on SH). Each sub-setting accepts an optional allowlist to restrict which tools are exposed. No tools are loaded by default. diff --git a/splunklib/ai/security.py b/splunklib/ai/security.py index 80936fcc9..8a933a6ce 100644 --- a/splunklib/ai/security.py +++ b/splunklib/ai/security.py @@ -70,11 +70,14 @@ def create_structured_prompt(instructions: str, data: str | dict[str, Any]) -> s external data (alert payloads, log entries, API responses, etc.) to reduce the risk of indirect prompt injection. - Example: - HumanMessage(content=create_structured_prompt( - instructions="Summarize this security alert and assess its severity.", - data=alert_payload, - )) + Example:: + + HumanMessage( + content=create_structured_prompt( + instructions="Summarize this security alert and assess its severity.", + data=alert_payload, + ) + ) """ return ( f"INSTRUCTIONS:\n" From b53717249eb88da1c02f206082c3f03ac202c7c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20J=C4=99drecki?= Date: Wed, 13 May 2026 16:18:59 +0200 Subject: [PATCH 2/3] Fix issues in pre-existing docstrings --- splunklib/searchcommands/eventing_command.py | 8 ++++---- splunklib/searchcommands/reporting_command.py | 7 +++---- splunklib/searchcommands/search_command.py | 4 ++-- splunklib/searchcommands/streaming_command.py | 10 +++++----- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/splunklib/searchcommands/eventing_command.py b/splunklib/searchcommands/eventing_command.py index a02af0e07..b3b703d58 100644 --- a/splunklib/searchcommands/eventing_command.py +++ b/splunklib/searchcommands/eventing_command.py @@ -106,15 +106,15 @@ class ConfigurationSettings(SearchCommand.ConfigurationSettings): doc=""" Specifies the maximum number of events that can be passed to the command for each invocation. - This limit cannot exceed the value of `maxresultrows` as defined in limits.conf_. Under SCP 1 you must - specify this value in commands.conf_. + This limit cannot exceed the value of `maxresultrows` as defined in `limits.conf + `_. Under SCP 1 you must + specify this value in `commands.conf + `_. Default: The value of `maxresultrows`. Supported by: SCP 2 - .. _limits.conf: http://docs.splunk.com/Documentation/Splunk/latest/admin/Limitsconf - """ ) diff --git a/splunklib/searchcommands/reporting_command.py b/splunklib/searchcommands/reporting_command.py index 317cc3dd2..119466953 100644 --- a/splunklib/searchcommands/reporting_command.py +++ b/splunklib/searchcommands/reporting_command.py @@ -216,15 +216,14 @@ class ConfigurationSettings(SearchCommand.ConfigurationSettings): doc=""" Specifies the maximum number of events that can be passed to the command for each invocation. - This limit cannot exceed the value of `maxresultrows` in limits.conf_. Under SCP 1 you must specify this - value in commands.conf_. + This limit cannot exceed the value of `maxresultrows` in `limits.conf + `_. Under SCP 1 you must specify this + value in `commands.conf `_. Default: The value of `maxresultrows`. Supported by: SCP 2 - .. _limits.conf: http://docs.splunk.com/Documentation/Splunk/latest/admin/Limitsconf - """ ) diff --git a/splunklib/searchcommands/search_command.py b/splunklib/searchcommands/search_command.py index 15add5f71..27b5bd0e4 100644 --- a/splunklib/searchcommands/search_command.py +++ b/splunklib/searchcommands/search_command.py @@ -169,7 +169,7 @@ def gen_record(self, **record): record = Option( doc=""" - **Syntax: record= + **Syntax:** record= **Description:** When `true`, records the interaction between the command and splunkd. Defaults to `false`. @@ -1166,7 +1166,7 @@ def dispatch( execute :code:`command_class`, pass :const:`None` as the value of :code:`module_name`. :param command_class: Search command class to instantiate and execute. - :type command_class: type + :type command_class: :class:`type` :param argv: List of arguments to the command. :type argv: list or tuple :param input_file: File from which the command will read data. diff --git a/splunklib/searchcommands/streaming_command.py b/splunklib/searchcommands/streaming_command.py index 0af4d61f7..fb401893f 100644 --- a/splunklib/searchcommands/streaming_command.py +++ b/splunklib/searchcommands/streaming_command.py @@ -133,18 +133,18 @@ class ConfigurationSettings(SearchCommand.ConfigurationSettings): doc=""" :const:`True`, if this command should be distributed to indexers. - Under SCP 1 you must either specify `local = False` or include this line in commands.conf_, if this command + Under SCP 1 you must either specify `local = False` or include this line in `commands.conf + `_, if this command should be distributed to indexers. - ..code: + .. code-block:: text + local = true Default: :const:`True` Supported by: SCP 2 - .. commands.conf_: http://docs.splunk.com/Documentation/Splunk/latest/Admin/Commandsconf - """, ) @@ -153,7 +153,7 @@ class ConfigurationSettings(SearchCommand.ConfigurationSettings): Specifies the maximum number of events that can be passed to the command for each invocation. This limit cannot exceed the value of `maxresultrows` in limits.conf. Under SCP 1 you must specify this - value in commands.conf_. + value in `commands.conf `_. Default: The value of `maxresultrows`. From 367dc12d592de4f583318944f6256c8d9088d479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20J=C4=99drecki?= Date: Wed, 13 May 2026 19:35:26 +0200 Subject: [PATCH 3/3] PR fixes --- splunklib/ai/agent.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/splunklib/ai/agent.py b/splunklib/ai/agent.py index 25ce52530..fe5ca51cd 100644 --- a/splunklib/ai/agent.py +++ b/splunklib/ai/agent.py @@ -58,7 +58,9 @@ class Agent(BaseAgent[OutputT]): """ Core entry point for interacting with LLMs in the Agentic Splunk SDK. - Agents are async context managers and must be used with `async with`:: + Agents are async context managers and must be used with `async with`: + + .. code-block:: python async with Agent( model=model,