Skip to content

Commit 6d37d97

Browse files
committed
Add hyperlight-codeact and monty-codeact skills
0 parents  commit 6d37d97

6 files changed

Lines changed: 1637 additions & 0 deletions

File tree

‎skills/hyperlight-codeact/SKILL.md‎

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
---
2+
description: 'Implement the CodeAct pattern with Hyperlight sandbox. Collapse multi-step tool chains into a single sandboxed Python execution that calls host tools via call_tool(). Tool names match Copilot CLI built-ins (view, create, edit, glob, grep, bash, sql, web_fetch, github_api) so the agent uses familiar names inside the sandbox. Use when a task requires chaining 3+ tool calls (data lookups, code search, computation, file manipulation, API calls). Trigger phrases: "codeact", "hyperlight sandbox", "chain tools together", "sandbox execution", "collapse tool calls", "run in sandbox".'
3+
name: hyperlight-codeact
4+
---
5+
# Hyperlight CodeAct
6+
7+
Collapse multi-step tool chains into a single sandboxed Python execution.
8+
Instead of N individual tool calls (model -> tool -> model -> tool ...), write
9+
one Python program that chains `call_tool()` for each step inside an isolated
10+
Hyperlight micro-VM.
11+
12+
Tool names inside the sandbox **match Copilot CLI built-in tools**:
13+
14+
| Copilot CLI tool | Sandbox `call_tool()` | What it does |
15+
|----------------------|-----------------------|----------------------------|
16+
| `view` | `view` | Read files / list dirs |
17+
| `create` | `create` | Create new files |
18+
| `edit` | `edit` | Surgical string replace |
19+
| `glob` | `glob` | Find files by pattern |
20+
| `grep` / `rg` | `grep` | Search file contents |
21+
| `bash` | `bash` | Run shell commands |
22+
| `sql` | `sql` | SQLite queries |
23+
| `web_fetch` | `web_fetch` | Fetch URLs |
24+
| `github-mcp-server-*`| `github_api` | GitHub REST API via `gh` |
25+
26+
## Trust model
27+
28+
The sandbox isolates model-generated **glue code** (the Python program), not
29+
the tool implementations. Tools run on the **host** with full process access.
30+
Sandboxed code can only reach the outside world through `call_tool()` bridges.
31+
32+
**Sandboxed:** The Python program. Cannot touch host FS, network, or processes.
33+
**Host-side:** Tool callbacks. They have whatever access the process has.
34+
**Implication:** Only register tools appropriate for the trust level. Use
35+
`--workspace` to restrict file tools to a directory tree.
36+
37+
## When to use CodeAct vs direct tool calls
38+
39+
**Reach for CodeAct when:**
40+
- Chaining 3+ tool calls (search -> read -> transform -> write).
41+
- Intermediate results need computation (filtering, aggregation, formatting).
42+
- Reducing latency and token usage matters.
43+
44+
**Stay with direct tool calls when:**
45+
- Only 1-2 tool calls needed.
46+
- Each call needs individual approval.
47+
- Tool outputs are large and need streaming.
48+
49+
## Quick start
50+
51+
```bash
52+
# 1. Discover tools (matches Copilot CLI tool names)
53+
python3 scripts/codeact.py --discover
54+
55+
# 2. Run code with auto-discovered tools
56+
python3 scripts/codeact.py --auto --workspace . --code '
57+
content = call_tool("view", path="README.md")
58+
print(f"README has {len(content.splitlines())} lines")
59+
'
60+
```
61+
62+
## Workflow
63+
64+
### Step 1 -- Discover tools
65+
66+
```bash
67+
python3 scripts/codeact.py --discover # JSON manifest
68+
python3 scripts/codeact.py --instructions # LLM-ready reference
69+
python3 scripts/codeact.py --discover --output tools.json # save manifest
70+
```
71+
72+
### Step 2 -- Write sandboxed code
73+
74+
Use `call_tool(name, **kwargs)` -- built-in global, no import needed.
75+
**All arguments must be keyword arguments.**
76+
77+
```python
78+
# Same names as Copilot CLI tools
79+
content = call_tool('view', path='src/main.py')
80+
files = call_tool('glob', pattern='**/*.py')
81+
hits = call_tool('grep', pattern='TODO', paths='src')
82+
result = call_tool('bash', command='git log --oneline -5')
83+
call_tool('edit', path='config.json', old_str='"debug": false', new_str='"debug": true')
84+
rows = call_tool('sql', query='SELECT * FROM users', db_path='app.db')
85+
data = call_tool('github_api', endpoint='/repos/owner/repo/issues')
86+
```
87+
88+
Chain by sequencing or nesting:
89+
90+
```python
91+
# Sequential: find files, read them, analyze
92+
for f in call_tool('glob', pattern='**/*.py', paths='src'):
93+
content = call_tool('view', path=f)
94+
if 'TODO' in content:
95+
print(f"{f}: {content.count('TODO')} TODOs")
96+
97+
# Nested: read a file found by glob
98+
content = call_tool('view', path=call_tool('glob', pattern='config.json')[0])
99+
```
100+
101+
### Step 3 -- Execute
102+
103+
```bash
104+
# Auto-discover + workspace scoping (recommended)
105+
python3 scripts/codeact.py --auto --workspace . --code '...'
106+
107+
# With saved manifest
108+
python3 scripts/codeact.py --manifest tools.json --code-file script.py
109+
110+
# Via stdin
111+
echo '{"tools": [...], "code": "..."}' | python3 scripts/codeact.py --stdin
112+
```
113+
114+
Output is always JSON: `{"stdout": "...", "stderr": "...", "exit_code": 0, "success": true}`
115+
116+
## Available scripts
117+
118+
### `scripts/codeact.py`
119+
Main executor. Key flags:
120+
- `--discover` / `--instructions` -- tool discovery
121+
- `--auto` -- auto-discover tools before running
122+
- `--workspace <dir>` -- restrict file tools to a directory tree
123+
- `--allowed-domains` -- allow sandbox-native HTTP
124+
- `--manifest <file>` -- load tools from JSON
125+
126+
## References
127+
128+
- **Tool patterns and chaining examples**: See [references/tool-patterns.md](references/tool-patterns.md)
129+
130+
## Prerequisites
131+
132+
- Python 3.10+
133+
- `hyperlight-sandbox[wasm,python_guest]` or build via `just python-build`
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# Tool Patterns & Chaining Reference
2+
3+
## CLI Tool Mapping
4+
5+
Sandbox tools mirror Copilot CLI built-in tools:
6+
7+
| Copilot CLI | Sandbox call_tool() | Host implementation |
8+
|---|---|---|
9+
| `view` | `call_tool('view', path=..., view_range=...)` | `Path.read_text()`, line slicing |
10+
| `create` | `call_tool('create', path=..., file_text=...)` | `Path.write_text()` (fails if exists) |
11+
| `edit` | `call_tool('edit', path=..., old_str=..., new_str=...)` | String replace (exactly 1 match) |
12+
| `glob` | `call_tool('glob', pattern=..., paths=...)` | `Path.glob()` |
13+
| `grep` / `rg` | `call_tool('grep', pattern=..., paths=..., glob=...)` | `rg` subprocess (requires ripgrep) |
14+
| `bash` | `call_tool('bash', command=..., timeout=...)` | `subprocess.run(shell=True)` |
15+
| `sql` | `call_tool('sql', query=..., db_path=...)` | `sqlite3` module |
16+
| `web_fetch` | `call_tool('web_fetch', url=..., method=...)` | `curl` subprocess |
17+
| `github-mcp-server-*` | `call_tool('github_api', endpoint=..., method=..., body=...)` | `gh api` subprocess |
18+
19+
## Always available (no dependencies)
20+
21+
| tool | description |
22+
|---|---|
23+
| `view` | Read file contents or list directory |
24+
| `create` | Create a new file (fails if exists) |
25+
| `edit` | Surgical string replacement in a file |
26+
| `glob` | Find files by glob pattern |
27+
| `bash` | Run shell commands (**high risk**) |
28+
| `sql` | Execute SQLite queries |
29+
30+
## Conditionally available
31+
32+
| tool | requires | description |
33+
|---|---|---|
34+
| `grep` | `rg` (ripgrep) | Search file contents |
35+
| `web_fetch` | `curl` | Fetch URLs |
36+
| `github_api` | `gh` CLI | GitHub REST API |
37+
38+
## Chaining Patterns
39+
40+
### Sequential: search -> read -> analyze
41+
42+
```python
43+
for f in call_tool('glob', pattern='**/*.py', paths='src'):
44+
content = call_tool('view', path=f)
45+
lines = content.splitlines()
46+
todos = [l for l in lines if 'TODO' in l]
47+
if todos:
48+
print(f"{f}: {len(todos)} TODOs")
49+
for t in todos:
50+
print(f" {t.strip()}")
51+
```
52+
53+
### Nested composition
54+
55+
```python
56+
# Read config found by glob
57+
config = call_tool('view',
58+
path=call_tool('glob', pattern='**/config.json')[0])
59+
```
60+
61+
### Fan-out / fan-in (multi-repo)
62+
63+
```python
64+
import json as _json
65+
repos = ['repo-a', 'repo-b', 'repo-c']
66+
all_issues = []
67+
for repo in repos:
68+
raw = call_tool('github_api', endpoint=f'/repos/myorg/{repo}/issues')
69+
all_issues.extend(_json.loads(raw))
70+
print(f"Total open issues: {len(all_issues)}")
71+
```
72+
73+
### Data pipeline with SQL
74+
75+
```python
76+
import json as _json
77+
78+
# Create and populate a table from API data
79+
call_tool('sql', query='CREATE TABLE IF NOT EXISTS issues (id INT, title TEXT, state TEXT)')
80+
81+
raw = call_tool('github_api', endpoint='/repos/owner/repo/issues?per_page=50')
82+
issues = _json.loads(raw)
83+
for issue in issues:
84+
call_tool('sql', query=f"INSERT INTO issues VALUES ({issue['number']}, '{issue['title']}', '{issue['state']}')")
85+
86+
# Query the data
87+
open_count = call_tool('sql', query='SELECT COUNT(*) as cnt FROM issues WHERE state="open"')
88+
print(f"Open issues: {open_count[0]['cnt']}")
89+
```
90+
91+
### Search and edit
92+
93+
```python
94+
# Find and fix a pattern across files
95+
hits = call_tool('grep', pattern='http://', paths='src', glob='*.py')
96+
for line in hits.strip().splitlines():
97+
filepath = line.split(':')[0]
98+
content = call_tool('view', path=filepath)
99+
if 'http://' in content and 'https://' not in content:
100+
call_tool('edit', path=filepath,
101+
old_str='http://', new_str='https://')
102+
print(f"Fixed: {filepath}")
103+
```
104+
105+
### Error-tolerant batch processing
106+
107+
```python
108+
import json as _json
109+
files = call_tool('glob', pattern='*.json', paths='config')
110+
for f in files:
111+
try:
112+
raw = call_tool('view', path=f)
113+
data = _json.loads(raw)
114+
print(f"{f}: OK ({len(data)} keys)")
115+
except Exception as e:
116+
print(f"{f}: ERROR - {e}")
117+
```
118+
119+
## Custom Tool Definitions
120+
121+
Add to the manifest JSON:
122+
123+
```json
124+
{
125+
"name": "count_lines",
126+
"description": "Count lines in a file",
127+
"parameters": {"path": {"type": "string", "required": true}},
128+
"implementation": {"type": "shell", "command_template": "wc -l < {path}"}
129+
}
130+
```
131+
132+
```json
133+
{
134+
"name": "calculate",
135+
"description": "Evaluate a math expression",
136+
"parameters": {"expression": {"type": "string", "required": true}},
137+
"implementation": {"type": "python", "code": "result = eval(expression, {'__builtins__': {}}, {'abs': abs, 'min': min, 'max': max, 'round': round})"}
138+
}
139+
```

0 commit comments

Comments
 (0)