Skip to content

Commit 2bd0931

Browse files
committed
new: inquire namespace to let the agent interactively ask questions to the user in a structured way.
1 parent 2cbb583 commit 2bd0931

File tree

7 files changed

+122
-5
lines changed

7 files changed

+122
-5
lines changed

docs/assets/make_ns.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131

3232
print(doc.strip())
3333
print()
34+
print("<details>")
35+
print("<summary><b>Show Tools</b></summary>")
36+
3437
print("| Tool | Description |")
3538
print("|------|-------------|")
3639

@@ -40,4 +43,5 @@
4043
doc = doc.strip().replace("\n", "<br>")
4144
print(f"| `{name}` | <pre>{doc}</pre> |")
4245

43-
print("")
46+
print("</details>")
47+
print()

docs/namespaces.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@ Nerve offers a rich set of predefined tools, organized in namespaces, that the a
66

77
Let the agent create its own tools in Python.
88

9+
<details>
10+
<summary><b>Show Tools</b></summary>
911
| Tool | Description |
1012
|------|-------------|
1113
| `create_tool` | <pre>Create a new tool or redefine an existing one by defining it as an annotated Python function.<br> Use this tool to implement the missing functionalities you need to perform your task.</pre> |
14+
</details>
1215

1316
## computer
1417

@@ -18,6 +21,8 @@ Let the agent create its own tools in Python.
1821
1922
Computer use primitives for mouse, keyboard, and screen.
2023

24+
<details>
25+
<summary><b>Show Tools</b></summary>
2126
| Tool | Description |
2227
|------|-------------|
2328
| `get_cursor_position` | <pre>Get the current mouse position.</pre> |
@@ -31,48 +36,78 @@ Computer use primitives for mouse, keyboard, and screen.
3136
| `mouse_right_click` | <pre>Click the right mouse button at the current mouse position.</pre> |
3237
| `mouse_scroll` | <pre>Scroll the mouse wheel in the given direction.</pre> |
3338
| `screenshot` | <pre>Take a screenshot of the current screen.</pre> |
39+
</details>
3440

3541
## filesystem
3642

3743
Read-only access primitives to the local filesystem.
3844

45+
<details>
46+
<summary><b>Show Tools</b></summary>
3947
| Tool | Description |
4048
|------|-------------|
4149
| `list_folder_contents` | <pre>List the contents of a folder on disk.</pre> |
4250
| `read_file` | <pre>Read the contents of a file from disk.</pre> |
51+
</details>
52+
53+
## inquire
54+
55+
Let the agent interactively ask questions to the user in a structured way.
56+
57+
<details>
58+
<summary><b>Show Tools</b></summary>
59+
| Tool | Description |
60+
|------|-------------|
61+
| `ask_for_confirmation` | <pre>Ask a confirmation question to the user.</pre> |
62+
| `ask_for_multiple_choice` | <pre>Ask a multiple choice question to the user.</pre> |
63+
| `ask_for_single_choice` | <pre>Ask a single choice question to the user.</pre> |
64+
| `ask_question` | <pre>Ask a question to the user.</pre> |
65+
</details>
4366

4467
## reasoning
4568

4669
Simulates the reasoning process at runtime.
4770

71+
<details>
72+
<summary><b>Show Tools</b></summary>
4873
| Tool | Description |
4974
|------|-------------|
5075
| `clear_thoughts` | <pre>If the reasoning process proved wrong, inconsistent or ineffective, clear your thoughts and start again.</pre> |
5176
| `think` | <pre>Adhere strictly to this reasoning framework, ensuring thoroughness, precision, and logical rigor.<br><br> ## Problem Decomposition<br><br> Break the query into discrete, sequential steps.<br> Explicitly state assumptions and context.<br><br> ## Stepwise Analysis<br><br> Address each step individually.<br> Explain the rationale, principles, or rules applied (e.g., mathematical laws, linguistic conventions).<br> Use examples, analogies, or intermediate calculations to illustrate reasoning.<br><br> ## Validation & Error Checking<br><br> Verify logical consistency at each step.<br> Flag potential oversights, contradictions, or edge cases.<br> Confirm numerical accuracy (e.g., recompute calculations).<br><br> ## Synthesis & Conclusion<br><br> Integrate validated steps into a coherent solution.<br> Summarize key insights and ensure the conclusion directly addresses the original query.</pre> |
77+
</details>
5278

5379
## shell
5480

5581
Let the agent execute shell commands.
5682

83+
<details>
84+
<summary><b>Show Tools</b></summary>
5785
| Tool | Description |
5886
|------|-------------|
5987
| `shell` | <pre>Execute a shell command on the local computer and return the output. Non interactive shell with a timeout of 30 seconds.</pre> |
88+
</details>
6089

6190
## task
6291

6392
Let the agent autonomously set the task as complete or failed.
6493

94+
<details>
95+
<summary><b>Show Tools</b></summary>
6596
| Tool | Description |
6697
|------|-------------|
6798
| `task_complete_success` | <pre>When your objective has been reached use this tool to set the task as complete.</pre> |
6899
| `task_failed` | <pre>Use this tool if you determine that the given goal or task is impossible given the information you have.</pre> |
100+
</details>
69101

70102
## time
71103

72104
Provides tools for getting the current date and time and waiting for a given number of seconds.
73105

106+
<details>
107+
<summary><b>Show Tools</b></summary>
74108
| Tool | Description |
75109
|------|-------------|
76110
| `current_time_and_date` | <pre>Get the current date and time.</pre> |
77111
| `wait` | <pre>Wait for a given number of seconds.</pre> |
112+
</details>
78113

nerve/cli/run.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,14 @@
2929

3030
@cli.command(
3131
context_settings={"allow_extra_args": True, "ignore_unknown_options": True, "help_option_names": ["-h", "--help"]},
32-
no_args_is_help=True,
3332
help="Execute an agent or a workflow.",
3433
)
3534
def run(
3635
ctx: typer.Context,
3736
input_path: t.Annotated[
3837
pathlib.Path,
3938
typer.Argument(help="Agent or workflow to execute"),
40-
],
39+
] = pathlib.Path("."),
4140
generator: t.Annotated[
4241
str,
4342
typer.Option("--generator", "-g", help="Generator to use"),

nerve/generation/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def _get_text_response(self, content: str) -> dict[str, t.Any]:
116116

117117
return {
118118
"role": "user",
119-
"content": "None of the tools were used.",
119+
"content": "None of the tools were used, interact with the user by executing the existing tools.",
120120
}
121121

122122
def _get_unknown_tool_response(self, tool_call_id: str, tool_name: str) -> dict[str, t.Any]:

nerve/models.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ class Configuration(BaseModel):
6666

6767
# TODO: add a "precall" to call the tool when the agent is started
6868

69+
# TODO: document these fields.
70+
6971
# used for versioning the agents
7072
version: str = "1.0.0"
7173
# the system prompt, the agent identity

nerve/tools/namespaces/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
# TODO: browser namespace (playwright wrapper)
2-
# TODO: namespace with tools to prompt the user like the create command

nerve/tools/namespaces/inquire.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
"""
2+
Let the agent interactively ask questions to the user in a structured way.
3+
"""
4+
5+
from typing import Annotated
6+
7+
import inquirer # type: ignore
8+
from pydantic import Field
9+
10+
11+
def ask_question(
12+
question: Annotated[
13+
str,
14+
Field(description="The question to ask the user.", examples=["What is your name?", "What is your age?"]),
15+
],
16+
) -> str:
17+
"""Ask a question to the user."""
18+
19+
print()
20+
return str(inquirer.prompt([inquirer.Text("question", message=question)])["question"]).strip()
21+
22+
23+
def ask_for_confirmation(
24+
question: Annotated[
25+
str,
26+
Field(
27+
description="The question to ask the user.", examples=["Do you want to continue?", "Do you want to quit?"]
28+
),
29+
],
30+
default: Annotated[bool, Field(description="The default answer to the question.", examples=[True, False])] = False,
31+
) -> str:
32+
"""Ask a confirmation question to the user."""
33+
34+
print()
35+
return (
36+
"YES" if inquirer.prompt([inquirer.Confirm("confirm", message=question, default=default)])["confirm"] else "NO"
37+
)
38+
39+
40+
def ask_for_single_choice(
41+
question: Annotated[
42+
str,
43+
Field(
44+
description="The question to ask the user.",
45+
examples=["What is your favorite color?", "What is your favorite food?"],
46+
),
47+
],
48+
choices: Annotated[
49+
list[str],
50+
Field(description="The choices to offer the user.", examples=["red", "blue", "green"]),
51+
],
52+
) -> str:
53+
"""Ask a single choice question to the user."""
54+
55+
print()
56+
return str(inquirer.prompt([inquirer.List("choice", message=question, choices=choices)])["choice"]).strip()
57+
58+
59+
def ask_for_multiple_choice(
60+
question: Annotated[
61+
str,
62+
Field(
63+
description="The question to ask the user.",
64+
examples=["What are your favorite colors?", "What are your favorite foods?"],
65+
),
66+
],
67+
choices: Annotated[
68+
list[str],
69+
Field(description="The choices to offer the user.", examples=["red", "blue", "green"]),
70+
],
71+
) -> str:
72+
"""Ask a multiple choice question to the user."""
73+
74+
print()
75+
return ", ".join(
76+
str(choice).strip()
77+
for choice in inquirer.prompt([inquirer.Checkbox("choices", message=question, choices=choices)])["choices"]
78+
)

0 commit comments

Comments
 (0)