cosmon-agent-sdk 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. cosmon_agent_sdk-0.1.0/.gitignore +8 -0
  2. cosmon_agent_sdk-0.1.0/CHANGELOG.md +37 -0
  3. cosmon_agent_sdk-0.1.0/LICENSE +31 -0
  4. cosmon_agent_sdk-0.1.0/PKG-INFO +188 -0
  5. cosmon_agent_sdk-0.1.0/README.md +127 -0
  6. cosmon_agent_sdk-0.1.0/examples/README.md +35 -0
  7. cosmon_agent_sdk-0.1.0/examples/async_quickstart.py +24 -0
  8. cosmon_agent_sdk-0.1.0/examples/attachments.py +30 -0
  9. cosmon_agent_sdk-0.1.0/examples/batch.py +37 -0
  10. cosmon_agent_sdk-0.1.0/examples/elicitation.py +48 -0
  11. cosmon_agent_sdk-0.1.0/examples/handoff.py +46 -0
  12. cosmon_agent_sdk-0.1.0/examples/playground.py +89 -0
  13. cosmon_agent_sdk-0.1.0/examples/quickstart.py +21 -0
  14. cosmon_agent_sdk-0.1.0/examples/sessions.py +98 -0
  15. cosmon_agent_sdk-0.1.0/examples/streaming.py +28 -0
  16. cosmon_agent_sdk-0.1.0/examples/structural_study.py +45 -0
  17. cosmon_agent_sdk-0.1.0/pyproject.toml +73 -0
  18. cosmon_agent_sdk-0.1.0/src/cosmon_agent_sdk/__init__.py +71 -0
  19. cosmon_agent_sdk-0.1.0/src/cosmon_agent_sdk/__main__.py +8 -0
  20. cosmon_agent_sdk-0.1.0/src/cosmon_agent_sdk/async_client.py +683 -0
  21. cosmon_agent_sdk-0.1.0/src/cosmon_agent_sdk/cli.py +175 -0
  22. cosmon_agent_sdk-0.1.0/src/cosmon_agent_sdk/client.py +234 -0
  23. cosmon_agent_sdk-0.1.0/src/cosmon_agent_sdk/discovery.py +69 -0
  24. cosmon_agent_sdk-0.1.0/src/cosmon_agent_sdk/elicit.py +186 -0
  25. cosmon_agent_sdk-0.1.0/src/cosmon_agent_sdk/errors.py +53 -0
  26. cosmon_agent_sdk-0.1.0/src/cosmon_agent_sdk/events.py +40 -0
  27. cosmon_agent_sdk-0.1.0/src/cosmon_agent_sdk/py.typed +0 -0
  28. cosmon_agent_sdk-0.1.0/tests/conftest.py +13 -0
  29. cosmon_agent_sdk-0.1.0/tests/e2e/test_e2e.py +492 -0
  30. cosmon_agent_sdk-0.1.0/tests/http_harness.py +89 -0
  31. cosmon_agent_sdk-0.1.0/tests/mcp_test_server.py +219 -0
  32. cosmon_agent_sdk-0.1.0/tests/test_cli.py +80 -0
  33. cosmon_agent_sdk-0.1.0/tests/test_discovery.py +45 -0
  34. cosmon_agent_sdk-0.1.0/tests/test_elicit_window.py +81 -0
  35. cosmon_agent_sdk-0.1.0/tests/test_mcp_async.py +407 -0
  36. cosmon_agent_sdk-0.1.0/tests/test_mcp_sync.py +199 -0
  37. cosmon_agent_sdk-0.1.0/tests/test_sessions.py +261 -0
  38. cosmon_agent_sdk-0.1.0/tests/test_status.py +53 -0
@@ -0,0 +1,8 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.egg-info/
4
+ build/
5
+ dist/
6
+ .pytest_cache/
7
+ .mypy_cache/
8
+ .venv/
@@ -0,0 +1,37 @@
1
+ # Changelog
2
+
3
+ All notable changes to `cosmon-agent-sdk` are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project follows
5
+ [Semantic Versioning](https://semver.org/) (while `0.x`, breaking changes may ride
6
+ minor bumps — see the design doc §6).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] — Unreleased
11
+
12
+ Initial release. The SDK is an [MCP](https://modelcontextprotocol.io) client for
13
+ the local MCP server the Cosmon app exposes — the agent is the tool.
14
+
15
+ ### Added
16
+ - `Client` / `AsyncClient` — discover the running app (via the descriptor; or
17
+ explicit `endpoint`/`token`), connect to its MCP server, and drive the agent.
18
+ Used as context managers; `AsyncClient` is native async, `Client` is a blocking
19
+ façade over it.
20
+ - `client.run(prompt, agent=, attachments=)` returning a `Run` / `AsyncRun`.
21
+ Consume it either way: `.text()` runs to completion and returns the agent's
22
+ final answer, or iterate it (`for event in run` / `async for`) to stream typed
23
+ `ToolCall` / `TextChunk` events (fed by MCP progress notifications).
24
+ - `client.discover()` → `DiscoverInfo` (login state, agents, model, runtime
25
+ readiness) from the `nexus://status` resource.
26
+ - **Interactive** runs via `on_question` / `on_confirm` handlers, mapped onto MCP
27
+ elicitation (`Question` / `Confirmation`). Supplying handlers declares the
28
+ elicitation capability; omitting both runs the agent unattended (no `ask_user`;
29
+ confirms auto-resolved — approve safe, decline dangerous). Because elicitation
30
+ is answered out of band, `.text()` never stalls or raises mid-run for input.
31
+ - Long client-side `timeout` (default 10 min) so multi-minute runs complete.
32
+ - Typed error family (`CosmonError` and subclasses, incl. `CosmonRunError`).
33
+ `py.typed` shipped.
34
+ - `cosmon` CLI: `doctor`, `run`, `ask` (headless; `--auto-approve`).
35
+
36
+ [Unreleased]: https://github.com/Cosmon-Inc/cosmon
37
+ [0.1.0]: https://github.com/Cosmon-Inc/cosmon
@@ -0,0 +1,31 @@
1
+ Copyright (c) 2026 Cosmon, Inc. All rights reserved.
2
+
3
+ NEXUS AGENT SDK — PROPRIETARY SOFTWARE LICENSE
4
+
5
+ This software and associated documentation files (the "Software") are the
6
+ proprietary and confidential property of Cosmon, Inc. ("Cosmon").
7
+
8
+ 1. License grant. Subject to your agreement to Cosmon's Terms of Service and any
9
+ applicable subscription or commercial agreement, Cosmon grants you a limited,
10
+ non-exclusive, non-transferable, revocable license to install and use the
11
+ Software solely to interface with the Cosmon Nexus application that you have
12
+ licensed and are authorized to use.
13
+
14
+ 2. Restrictions. You may not, except to the extent permitted by applicable law:
15
+ (a) copy, modify, or create derivative works of the Software; (b) reverse
16
+ engineer, decompile, or disassemble the Software; (c) redistribute, sublicense,
17
+ sell, rent, or lease the Software; or (d) remove or alter any proprietary
18
+ notices.
19
+
20
+ 3. Ownership. The Software is licensed, not sold. Cosmon retains all right, title,
21
+ and interest in and to the Software, including all intellectual property rights.
22
+
23
+ 4. No warranty. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT.
26
+
27
+ 5. Limitation of liability. IN NO EVENT SHALL COSMON BE LIABLE FOR ANY CLAIM,
28
+ DAMAGES, OR OTHER LIABILITY ARISING FROM OR IN CONNECTION WITH THE SOFTWARE OR
29
+ ITS USE.
30
+
31
+ For licensing inquiries, contact legal@cosmon.com.
@@ -0,0 +1,188 @@
1
+ Metadata-Version: 2.4
2
+ Name: cosmon-agent-sdk
3
+ Version: 0.1.0
4
+ Summary: Program the Nexus agent in your installed Cosmon app — drive SolidWorks, Abaqus, COMSOL, Fluent and more.
5
+ Project-URL: Homepage, https://cosmon.com
6
+ Project-URL: Documentation, https://docs.cosmon.com/sdk/overview
7
+ Project-URL: Repository, https://github.com/Cosmon-Inc/cosmon
8
+ Author-email: "Cosmon, Inc." <support@cosmon.com>
9
+ License: Copyright (c) 2026 Cosmon, Inc. All rights reserved.
10
+
11
+ NEXUS AGENT SDK — PROPRIETARY SOFTWARE LICENSE
12
+
13
+ This software and associated documentation files (the "Software") are the
14
+ proprietary and confidential property of Cosmon, Inc. ("Cosmon").
15
+
16
+ 1. License grant. Subject to your agreement to Cosmon's Terms of Service and any
17
+ applicable subscription or commercial agreement, Cosmon grants you a limited,
18
+ non-exclusive, non-transferable, revocable license to install and use the
19
+ Software solely to interface with the Cosmon Nexus application that you have
20
+ licensed and are authorized to use.
21
+
22
+ 2. Restrictions. You may not, except to the extent permitted by applicable law:
23
+ (a) copy, modify, or create derivative works of the Software; (b) reverse
24
+ engineer, decompile, or disassemble the Software; (c) redistribute, sublicense,
25
+ sell, rent, or lease the Software; or (d) remove or alter any proprietary
26
+ notices.
27
+
28
+ 3. Ownership. The Software is licensed, not sold. Cosmon retains all right, title,
29
+ and interest in and to the Software, including all intellectual property rights.
30
+
31
+ 4. No warranty. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT.
34
+
35
+ 5. Limitation of liability. IN NO EVENT SHALL COSMON BE LIABLE FOR ANY CLAIM,
36
+ DAMAGES, OR OTHER LIABILITY ARISING FROM OR IN CONNECTION WITH THE SOFTWARE OR
37
+ ITS USE.
38
+
39
+ For licensing inquiries, contact legal@cosmon.com.
40
+ License-File: LICENSE
41
+ Keywords: agent,cad,cae,cosmon,mcp,nexus,sdk
42
+ Classifier: Development Status :: 4 - Beta
43
+ Classifier: Intended Audience :: Developers
44
+ Classifier: License :: Other/Proprietary License
45
+ Classifier: Operating System :: OS Independent
46
+ Classifier: Programming Language :: Python :: 3
47
+ Classifier: Programming Language :: Python :: 3.10
48
+ Classifier: Programming Language :: Python :: 3.11
49
+ Classifier: Programming Language :: Python :: 3.12
50
+ Classifier: Programming Language :: Python :: 3.13
51
+ Classifier: Typing :: Typed
52
+ Requires-Python: >=3.10
53
+ Requires-Dist: anyio>=4
54
+ Requires-Dist: httpx>=0.24
55
+ Requires-Dist: mcp<2,>=1.28
56
+ Requires-Dist: pydantic>=2
57
+ Provides-Extra: dev
58
+ Requires-Dist: mypy>=1.8; extra == 'dev'
59
+ Requires-Dist: pytest>=7; extra == 'dev'
60
+ Description-Content-Type: text/markdown
61
+
62
+ # Cosmon Agent SDK (Python)
63
+
64
+ Program the **Nexus agent** in your installed, signed-in Cosmon app — drive
65
+ SolidWorks, Abaqus, COMSOL, Fluent, Ansys Mechanical and more from your own
66
+ Python. Your code brings the *caller*; the installed app brings the *capability*
67
+ (your login, your credits, the CAD software on your machine). **Your code never
68
+ holds a key.**
69
+
70
+ Under the hood the SDK is a small [MCP](https://modelcontextprotocol.io) client:
71
+ it discovers the running app, connects to the local MCP server it exposes, and
72
+ drives the agent through one `run` tool.
73
+
74
+ ## Install
75
+
76
+ ```bash
77
+ pip install cosmon-agent-sdk
78
+ ```
79
+
80
+ Then: open Cosmon, sign in, and turn on **Settings → Developer access**.
81
+
82
+ Check it's working:
83
+
84
+ ```bash
85
+ cosmon doctor
86
+ ```
87
+
88
+ ## Quickstart
89
+
90
+ `client.run()` returns a `Run`; get the agent's final answer with `.text()`:
91
+
92
+ ```python
93
+ from cosmon_agent_sdk import Client
94
+
95
+ with Client() as client:
96
+ answer = client.run("What's the max von Mises in bracket.sldprt?", agent="solidworks").text()
97
+ print(answer)
98
+ ```
99
+
100
+ Or **iterate** the run to stream it — it yields typed `ToolCall` / `TextChunk`
101
+ events (`.text()` and iterating are the two ways to consume a run; pick one):
102
+
103
+ ```python
104
+ import sys
105
+ from cosmon_agent_sdk import Client, TextChunk, ToolCall
106
+
107
+ with Client() as client:
108
+ for event in client.run("Run a static study on bracket.sldprt", agent="solidworks"):
109
+ if isinstance(event, TextChunk):
110
+ print(event.text, end="", flush=True) # answer, token by token
111
+ elif isinstance(event, ToolCall) and not event.finished:
112
+ print(f"[{event.summary}]", file=sys.stderr) # tool steps
113
+ ```
114
+
115
+ ## Attended vs unattended
116
+
117
+ Interactivity is set when you build the client, by whether you supply handlers:
118
+
119
+ - **Unattended (default)** — no handlers. The agent is never offered `ask_user`
120
+ (it proceeds on its own) and confirmations are auto-resolved (approve safe,
121
+ **decline dangerous**). `.text()` just runs to completion. This is the headless
122
+ path; put any decisions the agent might otherwise ask about in the prompt.
123
+ - **Interactive** — supply `on_question` and/or `on_confirm`. The app forwards the
124
+ agent's `ask_user` / `confirm_action` to your handlers (over MCP elicitation)
125
+ while `.text()` runs to completion. There's no event loop to drive — your
126
+ handlers are called as needed, so `.text()` never stalls waiting for an answer.
127
+
128
+ ```python
129
+ from cosmon_agent_sdk import Client, Question, Confirmation
130
+
131
+ def answer(question: Question) -> str:
132
+ return question.options[0] if question.options else "10mm seed size"
133
+
134
+ def approve(confirmation: Confirmation) -> bool:
135
+ return True # your policy here
136
+
137
+ with Client(on_question=answer, on_confirm=approve) as client:
138
+ print(client.run("Mesh the model and submit the job", agent="abaqus").text())
139
+ ```
140
+
141
+ ## Long runs
142
+
143
+ The agent can work for many minutes (mesh, solve, post-process). The client sets
144
+ a generous default `timeout` (10 minutes) and you can raise it:
145
+
146
+ ```python
147
+ with Client(timeout=1800) as client: # 30 minutes
148
+ client.run("Run a mesh-convergence study on bracket.sldprt", agent="solidworks").text()
149
+ ```
150
+
151
+ ## Async
152
+
153
+ `AsyncClient` is the async twin (for pipelines, FastAPI, etc.) — same surface,
154
+ `await`ed:
155
+
156
+ ```python
157
+ import asyncio
158
+ from cosmon_agent_sdk import AsyncClient
159
+
160
+ async def main() -> None:
161
+ async with AsyncClient() as client:
162
+ print(await client.run("what can you do?", agent="nexus").text())
163
+
164
+ asyncio.run(main())
165
+ ```
166
+
167
+ `Client`/`AsyncClient` and `Run`/`AsyncRun` are the sync/async pairs.
168
+
169
+ ## Command line
170
+
171
+ ```bash
172
+ cosmon doctor # check the connection, step by step
173
+ cosmon run "mesh and solve" --agent abaqus # stream the work (steps to stderr)
174
+ cosmon run "what can you do?" --agent nexus -q # -q: print just the final answer
175
+ ```
176
+
177
+ The CLI is headless (it can't answer `ask_user`); `--auto-approve` additionally
178
+ approves confirmation requests, including dangerous ones.
179
+
180
+ ## Notes
181
+
182
+ - **Discovery**: the app writes a `mcp-gateway.json` descriptor while Developer
183
+ access is on; the SDK reads it automatically. Override with the
184
+ `COSMON_SDK_DESCRIPTOR` environment variable.
185
+ - **Errors**: connecting / starting a run can raise `CosmonConnectionError`,
186
+ `CosmonAuthError`, `CosmonTimeoutError`, `CosmonProtocolError`; a run that fails
187
+ while running raises `CosmonRunError` from `.text()`.
188
+ - Docs: <https://docs.cosmon.com/>
@@ -0,0 +1,127 @@
1
+ # Cosmon Agent SDK (Python)
2
+
3
+ Program the **Nexus agent** in your installed, signed-in Cosmon app — drive
4
+ SolidWorks, Abaqus, COMSOL, Fluent, Ansys Mechanical and more from your own
5
+ Python. Your code brings the *caller*; the installed app brings the *capability*
6
+ (your login, your credits, the CAD software on your machine). **Your code never
7
+ holds a key.**
8
+
9
+ Under the hood the SDK is a small [MCP](https://modelcontextprotocol.io) client:
10
+ it discovers the running app, connects to the local MCP server it exposes, and
11
+ drives the agent through one `run` tool.
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ pip install cosmon-agent-sdk
17
+ ```
18
+
19
+ Then: open Cosmon, sign in, and turn on **Settings → Developer access**.
20
+
21
+ Check it's working:
22
+
23
+ ```bash
24
+ cosmon doctor
25
+ ```
26
+
27
+ ## Quickstart
28
+
29
+ `client.run()` returns a `Run`; get the agent's final answer with `.text()`:
30
+
31
+ ```python
32
+ from cosmon_agent_sdk import Client
33
+
34
+ with Client() as client:
35
+ answer = client.run("What's the max von Mises in bracket.sldprt?", agent="solidworks").text()
36
+ print(answer)
37
+ ```
38
+
39
+ Or **iterate** the run to stream it — it yields typed `ToolCall` / `TextChunk`
40
+ events (`.text()` and iterating are the two ways to consume a run; pick one):
41
+
42
+ ```python
43
+ import sys
44
+ from cosmon_agent_sdk import Client, TextChunk, ToolCall
45
+
46
+ with Client() as client:
47
+ for event in client.run("Run a static study on bracket.sldprt", agent="solidworks"):
48
+ if isinstance(event, TextChunk):
49
+ print(event.text, end="", flush=True) # answer, token by token
50
+ elif isinstance(event, ToolCall) and not event.finished:
51
+ print(f"[{event.summary}]", file=sys.stderr) # tool steps
52
+ ```
53
+
54
+ ## Attended vs unattended
55
+
56
+ Interactivity is set when you build the client, by whether you supply handlers:
57
+
58
+ - **Unattended (default)** — no handlers. The agent is never offered `ask_user`
59
+ (it proceeds on its own) and confirmations are auto-resolved (approve safe,
60
+ **decline dangerous**). `.text()` just runs to completion. This is the headless
61
+ path; put any decisions the agent might otherwise ask about in the prompt.
62
+ - **Interactive** — supply `on_question` and/or `on_confirm`. The app forwards the
63
+ agent's `ask_user` / `confirm_action` to your handlers (over MCP elicitation)
64
+ while `.text()` runs to completion. There's no event loop to drive — your
65
+ handlers are called as needed, so `.text()` never stalls waiting for an answer.
66
+
67
+ ```python
68
+ from cosmon_agent_sdk import Client, Question, Confirmation
69
+
70
+ def answer(question: Question) -> str:
71
+ return question.options[0] if question.options else "10mm seed size"
72
+
73
+ def approve(confirmation: Confirmation) -> bool:
74
+ return True # your policy here
75
+
76
+ with Client(on_question=answer, on_confirm=approve) as client:
77
+ print(client.run("Mesh the model and submit the job", agent="abaqus").text())
78
+ ```
79
+
80
+ ## Long runs
81
+
82
+ The agent can work for many minutes (mesh, solve, post-process). The client sets
83
+ a generous default `timeout` (10 minutes) and you can raise it:
84
+
85
+ ```python
86
+ with Client(timeout=1800) as client: # 30 minutes
87
+ client.run("Run a mesh-convergence study on bracket.sldprt", agent="solidworks").text()
88
+ ```
89
+
90
+ ## Async
91
+
92
+ `AsyncClient` is the async twin (for pipelines, FastAPI, etc.) — same surface,
93
+ `await`ed:
94
+
95
+ ```python
96
+ import asyncio
97
+ from cosmon_agent_sdk import AsyncClient
98
+
99
+ async def main() -> None:
100
+ async with AsyncClient() as client:
101
+ print(await client.run("what can you do?", agent="nexus").text())
102
+
103
+ asyncio.run(main())
104
+ ```
105
+
106
+ `Client`/`AsyncClient` and `Run`/`AsyncRun` are the sync/async pairs.
107
+
108
+ ## Command line
109
+
110
+ ```bash
111
+ cosmon doctor # check the connection, step by step
112
+ cosmon run "mesh and solve" --agent abaqus # stream the work (steps to stderr)
113
+ cosmon run "what can you do?" --agent nexus -q # -q: print just the final answer
114
+ ```
115
+
116
+ The CLI is headless (it can't answer `ask_user`); `--auto-approve` additionally
117
+ approves confirmation requests, including dangerous ones.
118
+
119
+ ## Notes
120
+
121
+ - **Discovery**: the app writes a `mcp-gateway.json` descriptor while Developer
122
+ access is on; the SDK reads it automatically. Override with the
123
+ `COSMON_SDK_DESCRIPTOR` environment variable.
124
+ - **Errors**: connecting / starting a run can raise `CosmonConnectionError`,
125
+ `CosmonAuthError`, `CosmonTimeoutError`, `CosmonProtocolError`; a run that fails
126
+ while running raises `CosmonRunError` from `.text()`.
127
+ - Docs: <https://docs.cosmon.com/>
@@ -0,0 +1,35 @@
1
+ # Examples
2
+
3
+ Runnable examples for the Cosmon Agent SDK.
4
+
5
+ ## Prerequisites
6
+
7
+ 1. Install the SDK — `pip install cosmon-agent-sdk` (or `pip install -e .` from the repo root).
8
+ 2. Open Cosmon, **sign in**, and turn on **Settings → Developer access**.
9
+ 3. Check the connection: `cosmon doctor`.
10
+
11
+ > **Dev builds:** the app's data dir is named `nexus`, not `Cosmon`, so the SDK's
12
+ > default descriptor path won't match. Point it at the path `cosmon doctor` reports:
13
+ >
14
+ > ```bash
15
+ > export COSMON_SDK_DESCRIPTOR="$HOME/Library/Application Support/nexus/mcp-gateway.json"
16
+ > ```
17
+
18
+ ## The examples
19
+
20
+ | File | What it shows |
21
+ |---|---|
22
+ | `quickstart.py` | The one-liner: `client.run(...).text()`. |
23
+ | `streaming.py` | Stream the run — iterate typed `ToolCall` / `TextChunk` events. |
24
+ | `structural_study.py` | Interactive run — answer the agent's questions and approve actions with `on_question` / `on_confirm`. |
25
+ | `batch.py` | Unattended batch over many files (no handlers). |
26
+ | `async_quickstart.py` | The async client (`AsyncClient`). |
27
+ | `playground.py` | Interactive REPL — drive the agent from your terminal. |
28
+
29
+ Run any of them:
30
+
31
+ ```bash
32
+ python examples/quickstart.py
33
+ python examples/playground.py solidworks
34
+ python examples/batch.py beam1.sldprt beam2.sldprt
35
+ ```
@@ -0,0 +1,24 @@
1
+ """Async — drive the agent from an asyncio program (FastAPI, pipelines, etc.).
2
+ Same surface as the sync client, awaited.
3
+
4
+ python examples/async_quickstart.py
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import asyncio
10
+
11
+ from cosmon_agent_sdk import AsyncClient
12
+
13
+
14
+ async def main() -> None:
15
+ async with AsyncClient() as client:
16
+ answer = await client.run(
17
+ "In one sentence, who are you and what can you help me with?",
18
+ agent="nexus",
19
+ ).text()
20
+ print(answer)
21
+
22
+
23
+ if __name__ == "__main__":
24
+ asyncio.run(main())
@@ -0,0 +1,30 @@
1
+ """Hand files to a run — the agent reads them alongside the prompt.
2
+
3
+ python examples/attachments.py <path> [<path> ...]
4
+
5
+ Relative paths are resolved against YOUR working directory (the SDK
6
+ absolutizes them before sending — the app's tool server has its own cwd), and
7
+ a missing file raises immediately instead of leaving the agent hunting for it.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import sys
13
+
14
+ from cosmon_agent_sdk import Client
15
+
16
+
17
+ def main() -> None:
18
+ paths = sys.argv[1:]
19
+ if not paths:
20
+ raise SystemExit("usage: python examples/attachments.py <path> [<path> ...]")
21
+ with Client() as client:
22
+ client.run(
23
+ "describe the attached file(s) in a couple of sentences",
24
+ agent="nexus",
25
+ attachments=paths,
26
+ ).text(live=True)
27
+
28
+
29
+ if __name__ == "__main__":
30
+ main()
@@ -0,0 +1,37 @@
1
+ """Run an analysis across many files, unattended.
2
+
3
+ A client with no ``on_question`` / ``on_confirm`` handlers runs the agent
4
+ unattended: it's never offered ``ask_user`` (it proceeds on its own) and
5
+ confirmations are auto-resolved — approve safe actions, decline dangerous ones.
6
+ So ``.text()`` just runs to completion. Put any decisions the agent might
7
+ otherwise ask about directly in the prompt. ``timeout`` caps each run so one
8
+ stuck file can't hang the whole batch.
9
+
10
+ python examples/batch.py beam1.sldprt beam2.sldprt
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import sys
16
+
17
+ from cosmon_agent_sdk import Client, CosmonError
18
+
19
+
20
+ def main() -> None:
21
+ files = sys.argv[1:] or ["beam1.sldprt", "beam2.sldprt"]
22
+ with Client(timeout=600) as client: # unattended; 10-minute ceiling per run
23
+ for path in files:
24
+ print(f"\n=== {path} ===")
25
+ try:
26
+ answer = client.run(
27
+ f"Run a static structural study on {path} with a 10mm mesh seed "
28
+ f"and report the peak von Mises stress.",
29
+ agent="solidworks",
30
+ ).text()
31
+ print(answer)
32
+ except CosmonError as err:
33
+ print(f" failed: {err}")
34
+
35
+
36
+ if __name__ == "__main__":
37
+ main()
@@ -0,0 +1,48 @@
1
+ """Answer the agent's questions and approval gates from the terminal.
2
+
3
+ python examples/elicitation.py
4
+
5
+ Passing handlers declares the elicitation capability: `on_question` answers
6
+ `ask_user`, `on_confirm` answers confirmation gates — both out of band while
7
+ `.text()` blocks, so expect the prompts to appear mid-call. (Passing only
8
+ `on_confirm` runs question-free: the agent is never offered ask_user, but
9
+ every approval gate still reaches the handler.) `live=True` prints the run
10
+ live while you wait; the returned text stays the authoritative transcript.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ from cosmon_agent_sdk import Client, Confirmation, Question
16
+
17
+ DIM = "\x1b[2m"
18
+ RESET = "\x1b[0m"
19
+
20
+ def answer_question(question: Question) -> str:
21
+ # The app shows a countdown bar for this; a terminal can at least say it.
22
+ window = int(question.expires_in)
23
+ print(f"\n{DIM}[agent asks — ~{window}s before it proceeds without you]{RESET} {question.prompt}")
24
+ for index, option in enumerate(question.options, start=1):
25
+ print(f" {index}) {option}")
26
+ # An empty answer is NOT a submission (a stray Enter would read as "no
27
+ # answer" and the agent would proceed on its own judgment) — re-prompt,
28
+ # exactly like the app disables its submit button on empty text.
29
+ while not (raw := input("answer> ").strip()):
30
+ pass
31
+ if question.options and raw.isdigit() and 1 <= int(raw) <= len(question.options):
32
+ return question.options[int(raw) - 1]
33
+ return raw
34
+
35
+ def approve(confirmation: Confirmation) -> bool:
36
+ return input(f"\n[confirm] {confirmation.summary} [y/N]> ").strip().lower() in ("y", "yes")
37
+
38
+
39
+ def main() -> None:
40
+ with Client(on_confirm=approve, on_question=answer_question) as client:
41
+ client.run(
42
+ "please ask me a question with multiple choices and then summarize the answer in one sentence",
43
+ agent="nexus",
44
+ ).text(live=True)
45
+
46
+
47
+ if __name__ == "__main__":
48
+ main()
@@ -0,0 +1,46 @@
1
+ """A run that spans a handoff chain, answered from the terminal.
2
+
3
+ python examples/handoff.py
4
+
5
+ The entry agent hands off mid-run; `live=True` labels the stream with the
6
+ agent in control (`[solidworks]`, `[comsol]`, …) so multi-agent runs stay
7
+ attributable. Questions from ANY agent in the chain reach `on_question`;
8
+ without `on_confirm`, approval gates auto-resolve (approve safe, decline
9
+ dangerous), so the handoff itself proceeds unprompted.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from cosmon_agent_sdk import Client, Confirmation, Question
15
+
16
+ DIM = "\x1b[2m"
17
+ RESET = "\x1b[0m"
18
+
19
+ def answer_question(question: Question) -> str:
20
+ print(f"\n{DIM}[agent asks]{RESET} {question.prompt}")
21
+ for index, option in enumerate(question.options, start=1):
22
+ print(f" {index}) {option}")
23
+ raw = input("answer> ").strip()
24
+ if question.options and raw.isdigit() and 1 <= int(raw) <= len(question.options):
25
+ return question.options[int(raw) - 1]
26
+ return raw
27
+
28
+ def approve(confirmation: Confirmation) -> bool:
29
+ return input(f"\n[confirm] {confirmation.summary} [y/N]> ").strip().lower() in ("y", "yes")
30
+
31
+
32
+ def main() -> None:
33
+ with Client(
34
+ # on_confirm=approve,
35
+ on_question=answer_question
36
+ ) as client:
37
+ client.run(
38
+ "please handoff to the comsol agent and ask me a multiple-choice "
39
+ "question through the ask question tool call, then summarize the "
40
+ "answer in one sentence",
41
+ agent="solidworks",
42
+ ).text(live=True)
43
+
44
+
45
+ if __name__ == "__main__":
46
+ main()