Metadata-Version: 2.5
Name: artificer-agent
Version: 0.1.0a1
Summary: An AI assistant on Athanore: a chat that manages agent workflows
Project-URL: Homepage, https://github.com/artificer-ai/artificer
Project-URL: Repository, https://github.com/artificer-ai/artificer
Project-URL: Issues, https://github.com/artificer-ai/artificer/issues
Author-email: Scott Russell <scrussell24@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: agents,assistant,athanore,llm,workflows
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Build Tools
Classifier: Typing :: Typed
Requires-Python: >=3.13
Requires-Dist: athanore>=1.4.1
Requires-Dist: httpx>=0.28
Requires-Dist: pydantic>=2.7
Requires-Dist: rich
Requires-Dist: typer
Description-Content-Type: text/markdown

# Artificer

An AI assistant on [Athanore](https://github.com/artificer-ai/athanore).
Artificer works like an engineering manager: it does not do the work
itself, it writes, registers and runs the Athanore workflows and plugins
that do. Each chat is one durable Athanore run; the UI is a plain chat.

**Status: prototype.** The chat loop (server, REPL, resume, restart
durability) works. The manager tools and the web UI are next.

## Prerequisites

- Python 3.13 and [uv](https://docs.astral.sh/uv/)
- [pi](https://github.com/earendil-works/pi) and its ACP adapter:
  `npm i -g @earendil-works/pi-coding-agent pi-acp`
- An API key for the model provider pi should use, in the shell that
  starts the server (for example `OPENROUTER_API_KEY` or
  `ANTHROPIC_API_KEY`). Credentials are never stored in Artificer's home.

## Run it

```sh
uv sync
uv run artificer doctor           # node, pi, pi-acp, a provider key, a model, the home
uv run artificer serve            # chat at http://127.0.0.1:2424, API + dashboard at :4002
uv run artificer chat "hello"     # in another shell: a REPL; /quit ends, Ctrl-D detaches
uv run artificer chats            # list chats
uv run artificer chat --resume <run id>
```

In the chat, typing `/` opens a menu of slash commands that look things
up without asking Artificer: `/workflows [filter]` lists the registered
workflows (pool, node count, occupancy), `/runs [status] [workflow]`
lists runs newest first (`/runs failed`, `/runs completed feature_adder`),
and `/default-model` shows the pi home's default model and its limits.
They run in the page against the API and are not part of the
conversation; `/quit` still ends a chat.

`serve --host 0.0.0.0` puts it on the network; Athanore then requires an
operator token, which `serve` generates into the home and prints, and
the UI asks for once. The Athanore dashboard on `:4002` shows every run
Artificer starts — work logs, transcripts, requests — so the chat never
has to.

`serve --unsafe` turns operator authentication off (and binds `0.0.0.0`
unless you give `--host`), for a home network where copying a token to
every phone and tablet is not worth it. It prints a warning first.
Anyone who can reach the port can then run the manager, read every chat
and every file in the workspace, and use the dashboard — and because
registering a workflow means running the code it names, that is
arbitrary code execution as the user running the server. Agents' own
task tokens are unaffected. Athanore's `athanore serve` has no such
flag yet.

On a loopback bind Athanore needs no token: the bind is the
authentication. A browser can defeat that — a page served from a domain
whose DNS answer is `127.0.0.1` is same-origin with the local server, so
neither the missing token nor the absent CORS headers stand in its way.
Artificer therefore checks the `Host` header on both ports and answers
only for IP literals, `localhost`, `.localhost`, `.local`, this
machine's hostname and whatever `--host` you gave; anything else gets
`421`. Behind a reverse proxy or a custom DNS name, name it in
`ARTIFICER_ALLOWED_HOSTS` (comma-separated; `*` turns the check off).

Everything Artificer owns lives in `~/.artificer` (`ARTIFICER_HOME`
overrides): pi's isolated home (`pi/` — settings, extensions, skills,
sessions), the assistant's memory (`memory/`), its workspace, and the
Athanore database. pi never reads your `~/.pi/agent`. To pick a model,
edit `~/.artificer/pi/settings.json` (`defaultProvider`, `defaultModel`).

## Develop

```sh
uv run pytest -q                  # the chat and manager loops on athanore's fake ACP agent
uv run ruff check . && uv run ruff format .
cd web && npm install && npm run dev   # the UI on :5174, proxying /api to :4002
npm -C web run build              # → artificer/web/dist, what serve and the wheel use
./scripts/build.sh --check        # the gate, the SPA, the wheel — and proof the wheel has the UI
uv run python -m artificer.eval.battery --mock-only   # the prompt-eval harness; see artificer/eval/README.md
```
