# AgentGear

<p align="center">
  <img src="https://raw.githubusercontent.com/debpanda/agentgear/main/docs/assets/agentgear-logo.svg" alt="AgentGear logo" width="220" />
</p>

AgentGear is an open-source, cloud-ready observability and prompt management platform for LLM-powered agents. It ships a Python SDK, FastAPI backend, React + Vite dashboard, and Typer CLI so you can log prompts, runs, spans, costs, and latency across modern frameworks (OpenAI Agent SDK, Google ADK, LangChain, LlamaIndex, LiteLLM, custom Python).

---

## Quick Start

### Prerequisites
- Python 3.10+
- Node 18+ (with npm/pnpm/yarn)
- SQLite (default) or Postgres (for cloud)

### 1) Install SDK
```bash
pip install agentgear-ai
```
> Package name is `agentgear-ai`, import path remains `import agentgear`.

### 2) Initialize backend (SQLite dev)
```bash
agentgear init-db
agentgear ui  # starts FastAPI via uvicorn --reload on :8000
```

### 3) Launch dashboard (served from the Python package)
```bash
agentgear ui  # serves API + packaged React dashboard on :8000
# open http://localhost:8000
# first visit prompts you to set an admin username/password
```

### 4) Create project + token (from CLI)
```bash
agentgear create-project --name "My Project"
agentgear create-token --project <project_id>
```
Copy the token (shown once). Use it in SDK calls via `X-AgentGear-Key`.

---

## SDK Usage

### Configure client
```python
from agentgear import AgentGearClient

# Remote mode (FastAPI running elsewhere)
client = AgentGearClient(
    base_url="https://your-api.example.com",
    api_key="ag_live_...",
    project_id="proj_123",
    local=False,
)

# Local mode (writes directly to SQLite, no API key needed)
local_client = AgentGearClient(
    project_id="proj_123",
    local=True,
)
```

### Observe decorator
```python
from agentgear import observe

@observe(client, name="chat-complete", prompt_version_id="pv_abc")
def complete(prompt: str) -> str:
    # call your LLM here
    return "response"

complete("hi")
```
Captures args, output, latency, prompt version, and errors; logs a run.

### Trace spans
```python
from agentgear import trace

run = client.log_run(name="pipeline", input_text="user input")
with trace(client, run_id=run["id"], name="retrieve") as span:
    # retrieval work
    pass
with trace(client, run_id=run["id"], name="generate", parent_id=span.span_id):
    # generation work
    pass
```

### Prompt templating
```python
from agentgear import Prompt

prompt = Prompt(name="greeting", template="Hello {{ name }}!", version_id="pv_1")
rendered = prompt.render(name="AgentGear")
# register / version prompt
client.register_prompt(name=prompt.name, content=prompt.template, description="Greeting")
client.create_prompt_version(prompt_id="<prompt_id>", content="Hi {{ name }}!")
```

### OpenAI chat instrumentation
```python
from openai import OpenAI
from agentgear.sdk.integrations.openai import instrument_openai_chat

raw_client = OpenAI(api_key="sk-...")
client = AgentGearClient(base_url="http://localhost:8000", api_key="ag_live_...", project_id="proj_123")
instrumented = instrument_openai_chat(raw_client, agentgear=client, model="gpt-4o", prompt_version_id="pv_123")

resp = instrumented.chat.completions.create(model="gpt-4o", messages=[{"role":"user","content":"Hello"}])
```

---

## Backend (FastAPI)

### Core entities
- **Project**: id, name, description, created_at
- **API Token**: id, project_id, key_hash (SHA-256), scopes, revoked, last_used_at
- **Prompt / PromptVersion**: registry + versioning
- **Run**: logged LLM call with tokens/cost/latency
- **Span**: child spans for workflows

### Auth
- Header: `X-AgentGear-Key: <token>`
- Scopes (examples): `runs.write`, `prompts.read`, `prompts.write`, `tokens.manage`
- Admin dashboard login: first visit prompts you to set username/password. If you forget, set `AGENTGEAR_ADMIN_USERNAME` and `AGENTGEAR_ADMIN_PASSWORD` to override.
- Local mode (`AGENTGEAR_LOCAL_MODE=true`) bypasses token enforcement for dev.

### Key endpoints
- `POST /api/projects`, `GET /api/projects`, `GET /api/projects/{id}`
- `POST /api/projects/{id}/tokens`, `GET /api/projects/{id}/tokens`, `DELETE /api/projects/{id}/tokens/{token_id}`
- `POST /api/prompts`, `GET /api/prompts`, `GET /api/prompts/{id}`, `POST /api/prompts/{id}/versions`, `GET /api/prompts/{id}/versions`
- `POST /api/runs`, `GET /api/runs`, `GET /api/runs/{id}`
- `POST /api/spans`, `GET /api/spans?run_id=`
- `GET /api/metrics/summary`, `GET /api/health`

### Configuration (env)
| Var | Default | Description |
| --- | --- | --- |
| `AGENTGEAR_DATABASE_URL` | `sqlite:///./agentgear.db` | DB connection (Postgres e.g. `postgresql+psycopg://user:pass@host/db`) |
| `AGENTGEAR_API_HOST` | `0.0.0.0` | Bind host |
| `AGENTGEAR_API_PORT` | `8000` | Bind port |
| `AGENTGEAR_SECRET_KEY` | `agentgear-dev-secret` | Signing/crypto secret |
| `AGENTGEAR_ALLOW_ORIGINS` | `*` | CORS allowlist |
| `AGENTGEAR_LOCAL_MODE` | `false` | If true, bypasses auth (dev only) |
| `AGENTGEAR_ADMIN_USERNAME` | `None` | Optional: override admin login username (e.g. for reset) |
| `AGENTGEAR_ADMIN_PASSWORD` | `None` | Optional: override admin login password (e.g. for reset) |

---

## Dashboard (React + Vite + Tailwind)
- `/projects`: list + create projects
- `/projects/:id`: overview (stats, prompts, runs, tokens)
- `/projects/:id/tokens`: create/revoke tokens (shows raw token once)
- `/runs`: list runs with latency/cost
- `/runs/:id`: run detail + spans
- `/prompts`: prompt registry
- `/prompts/:id`: versions + add version

### Run frontend locally
```bash
cd frontend
npm install
npm run dev
# set API target if not localhost:
# export VITE_AGENTGEAR_API=http://localhost:8000
```
> Production installs get the built dashboard bundled inside the Python package and served from `/` when you run `agentgear ui`.

---

## CLI (Typer)
```bash
agentgear --help
agentgear init-db
agentgear create-project --name "Demo"
agentgear create-token --project <project_id> --scopes runs.write prompts.read prompts.write tokens.manage
agentgear list-projects
agentgear demo-data
agentgear ui --host 0.0.0.0 --port 8000 --reload
```

---

## Deployment

### Postgres example
```bash
export AGENTGEAR_DATABASE_URL="postgresql+psycopg://user:pass@host:5432/agentgear"
export AGENTGEAR_LOCAL_MODE=false
agentgear init-db
agentgear ui --host 0.0.0.0 --port 8000 --reload=false
```

### Production notes
- Use Postgres for durability and concurrency.
- Keep `AGENTGEAR_SECRET_KEY` secret.
- Issue per-project tokens with least-privilege scopes.
- Put FastAPI behind HTTPS + reverse proxy (nginx, Caddy, ALB).
- Restrict CORS to trusted origins.

---

## Data Model Overview
- `projects`: id, name, description, created_at
- `api_keys`: id, project_id, key_hash, scopes (JSON), revoked, last_used_at
- `prompts`: id, project_id, name, description
- `prompt_versions`: id, prompt_id, version, content, metadata
- `runs`: id, project_id, prompt_version_id, input/output, tokens, cost, latency, error, metadata
- `spans`: id, project_id, run_id, parent_id, name, timing, metadata

---

## Testing & Dev
- Lint (Python): `ruff check .`
- Tests (Python): `pytest`
- Frontend lint: `npm run lint --prefix frontend`
- Frontend test (placeholder): `npm run test --prefix frontend`

---

## Releasing to PyPI (manual)
```bash
pip install build twine
python -m build
twine upload dist/*
```

---

## Contributing
See `CONTRIBUTING.md` for setup, standards, and review process. PRs welcome!

## License
Apache 2.0. See `LICENSE`.
