cape.agent.agentcntl: Controller class for CAPE agent¶
This module provdes the class AgentCntl which serves as an
object-oriented interface to the CAPE agentic capability and interface.
Most of the actual agent loop, including passing user responses on to
an external LLM and processing the results, is implemented by methods of
AgentCntl.
The module-level list EDIT_FILE_ALLOW_LIST is a registry of
POSIX-style file names, relative to the folder in which the agent is
launched, that skills may append to at run time (e.g. the fix-json
skill registers the file the user asked to repair). The
cape.agent.skills.fileedit module merges these names into its
edit allow-list in addition to its own static patterns and the files
provided by cape.cfdx.cntl.Cntl.get_edit_allowlist().
- class cape.agent.agentcntl.AgentCntl(fname: str | None = None)¶
Controller class for the CAPE agentic interface
This class implements the agent loop behind
cape --agentic: reading user input, passing messages to an external LLM server, and processing any tool calls in its response. The tools and skills exposed to the LLM are filtered based on the options for the model in use (seecape.agent.options); user skills are discovered from the folder in which the agent is launched (seecape.agent.skills).- Call:
>>> cntl = AgentCntl(fname=None)
- Inputs:
- fname: {
None} |str Name of CAPE-agentic JSON file (defaults to
"cape-agent.json")
- fname: {
- Outputs:
- cntl:
AgentCntl Controller for the CAPE agent loop
- cntl:
- client¶
openai.OpenAIClient interface to LLM server
- launch_cli_task(messages: list, cmdlist: list)¶
Launch a typed command as a background task
Runs cmdlist as a background task and records the launch in the conversation history.
- launch_tool_task(name: str, kwargs: dict, result: dict) dict¶
Launch a tool call as a background task
Returns the tool’s immediate result; its full result is delivered as a follow-up message when the task completes.
- reap_tasks(section_handler=None)¶
Notify user and history of completed background tasks
- run_agent(user_message: str, spinner: bool = True, capture_subprocess: bool = False, section_handler=None) dict¶
Run one pass of model with multi-round tool calling
Run one user turn with up to MaxToolCallLoops rounds of tool calls. This allows the agent to chain tool calls, e.g., calling
cape_find()followed bycape_c()with the results from the first call.- Inputs:
- user_message:
str User prompt or direct command
- spinner: {
True} |False Show the readline thinking spinner; Textual supplies its own
- capture_subprocess: {
False} |True Pipe direct system-command output through
sys.stdout- section_handler: {
None} | callable Optional presentation hook called at the start and end of reasoning and tool sections
- user_message:
- Outputs:
- result:
dict Counts of tool calls and failures for this turn
- result:
- class cape.agent.agentcntl.AgentResult(returncode, result)¶
- result¶
Alias for field number 1
- returncode¶
Alias for field number 0
- cape.agent.agentcntl.genr8_image_message(images: list) dict¶
Build a user message carrying image content for the model
- cape.agent.agentcntl.genr8_system_prompt(skills: dict, tools: dict | None = None) str¶
Build the system prompt, listing available agent skills
Tool-specific guidance (e.g. for
cape_findorview_subfig) is included only when the corresponding tool is exposed to the model, and available skills are listed at the end.- Call:
>>> prompt = genr8_system_prompt(skills, tools=None)
- Inputs:
- skills:
dict[skills.skillbase.Skill] Map of skill names to skill definitions
- tools: {
None} |dict Map of tool names exposed to the model
- skills:
- Outputs:
- prompt:
str System prompt for the LLM
- prompt:
- cape.agent.agentcntl.get_reasoning_text(message) str¶
Get normalized reasoning text from a completion message
- Inputs:
- message:
object Chat-completion response message
- message:
- Outputs:
- text:
str Reasoning text, or an empty string when none was exposed
- text:
- cape.agent.agentcntl.show_reasoning(message, framed: bool = True) bool¶
Display post-response reasoning content when available
This uses the nonstandard
reasoningfield exposed by current vLLM servers, withreasoning_contentas a fallback for older compatible servers. The OpenAI Python client keeps unknown response fields as model extras, sogetattr()works even when the installed SDK does not declare either field.- Call:
>>> shown = show_reasoning(message)
- Inputs:
- message:
object Chat-completion response message
- framed: {
True} |False Print the classic prompt and horizontal rules
- message:
- Outputs:
- shown:
bool Whether nonempty reasoning content was displayed
- shown: