# write_tool — Manual

## What it does
Writes Python source code to `tools/<name>.py` and immediately reloads it into the system.
The new tool becomes a permanent part of your capabilities — available in every future session.

## Parameters
- `name` (string, required) — tool filename without `.py`, e.g. `"task_manager"`
- `code` (string, required) — full Python source code (see format below)

## Required code format
Every tool file must define exactly these four things at module level, in this order:

```python
name = "tool_name"          # must match the filename
description = "When and why to use this tool. Be specific — this is what you read to decide whether to call it."
parameters = {
    "type": "object",
    "properties": {
        "param1": {"type": "string", "description": "What this parameter is for"},
        "param2": {"type": "integer", "description": "..."},
    },
    "required": ["param1"],
}

async def execute(params: dict) -> str:
    value = params["param1"]
    # your implementation here
    return "result as a plain string"
```

Rules:
- NO classes
- NO print() at module level
- `execute` MUST be `async`
- `execute` MUST return a plain `str` — not dict, not None
- Raise an exception to signal failure (do not return error dicts)
- Put imports inside `execute()` or at the top of the file — both are fine

## Data persistence
If the tool needs to store data between calls, use a JSON file inside the `tools/` directory:

```python
import json, os

DATA_FILE = os.path.join(os.path.dirname(__file__), "my_tool_data.json")

def _load():
    if os.path.exists(DATA_FILE):
        with open(DATA_FILE) as f:
            return json.load(f)
    return {}

def _save(data):
    with open(DATA_FILE, "w") as f:
        json.dump(data, f, ensure_ascii=False, indent=2)
```

## Full example — a simple note-taking tool

```python
import json, os

name = "notes"
description = (
    "Save and retrieve short text notes by key. "
    "Use this to remember things across sessions: facts, preferences, reminders. "
    "Actions: save (store a note), get (retrieve by key), list (show all keys)."
)
parameters = {
    "type": "object",
    "properties": {
        "action": {"type": "string", "enum": ["save", "get", "list"]},
        "key":   {"type": "string", "description": "Note identifier"},
        "value": {"type": "string", "description": "Note content (for save)"},
    },
    "required": ["action"],
}

_FILE = os.path.join(os.path.dirname(__file__), "notes_data.json")

async def execute(params: dict) -> str:
    action = params["action"]
    data = json.loads(open(_FILE).read()) if os.path.exists(_FILE) else {}

    if action == "save":
        key, value = params["key"], params["value"]
        data[key] = value
        open(_FILE, "w").write(json.dumps(data, ensure_ascii=False, indent=2))
        return f"Saved: {key}"

    if action == "get":
        key = params["key"]
        if key not in data:
            raise KeyError(f"Note '{key}' not found. Use action=list to see all keys.")
        return data[key]

    if action == "list":
        if not data:
            return "No notes saved yet."
        return "Saved notes: " + ", ".join(data.keys())

    raise ValueError(f"Unknown action: {action}")
```

## What write_tool checks before writing
- `name`, `description`, `parameters`, `async def execute` must all be present in the code
- Name must not start with `_`

If the check fails, you get a clear error with the list of what's missing.
If the file loads but has a Python error, you get the exact traceback.

## After a successful call
The tool is registered and added to `tools/enabled.json`.
It will be available starting from the **next user message** — not the current one.
