# Quickstart

Get from `pip install` to a running multi-agent flow in under 5 minutes.

> 🇯🇵 日本語版は [quickstart.ja.md](quickstart.ja.md) を参照。

---

## 1. Install

Pick the extras you need (everything else stays out of your dependency tree):

```bash
pip install praxia                 # Core (CLI + JSON memory + 6 skills + 3 flows)
pip install "praxia[ui]"           # + Streamlit UI
pip install "praxia[connectors]"   # + Box / SharePoint / Dropbox / Drive / kintone / Salesforce
pip install "praxia[office]"       # + PDF / Word / PowerPoint / Excel parsing
pip install "praxia[audio]"        # + Whisper STT + OpenAI / ElevenLabs TTS
pip install "praxia[all]"          # Everything (excluding *-local variants)
```

## 2. Configure once — keys live in one place

Praxia reads configuration from these sources (first match wins):

1. **Process environment variables**
2. **`.env` file** in the working directory
3. **`.praxia/config.toml`** (managed by `praxia config`)

The easiest path:

```bash
cp .env.example .env
# Edit .env and fill in just the keys you actually use
```

Or use the interactive wizard:

```bash
praxia config init     # walks through the keys most users need
praxia config show     # display current resolved config (secrets masked)
praxia config path     # show where keys are resolved from
praxia config set ANTHROPIC_API_KEY sk-ant-xxx
praxia config get OPENAI_API_KEY
```

**Minimum**: set at least one LLM provider key. `auto_detect()` picks the
first one it finds in this priority order:

```bash
ANTHROPIC_API_KEY=sk-ant-...      # → claude (recommended for tool use)
OPENAI_API_KEY=sk-...             # → chatgpt (also enables Whisper STT + OpenAI TTS)
GEMINI_API_KEY=...                # → gemini (long context / multimodal)
DEEPSEEK_API_KEY=...              # → deepseek (Chinese SOTA, ~1/10 cost)
MISTRAL_API_KEY=...               # → mistral (EU-friendly, mistral-large-latest)
XAI_API_KEY=...                   # → grok
DASHSCOPE_API_KEY=...             # → qwen (Alibaba)
COHERE_API_KEY=...                # → command-r (enterprise RAG)
PERPLEXITY_API_KEY=...            # → perplexity (web-search-augmented)
GROQ_API_KEY=...                  # → llama (3.3 70B, hundreds of tok/s)
TOGETHERAI_API_KEY=...            # → llama via Together
```

Pass an explicit alias any time with `--model <alias>`:
`claude` / `chatgpt` / `gemini` / `deepseek` / `mistral` / `grok` / `qwen` /
`command-r` / `perplexity` / `llama` / `gemma` / `phi` / `llama-local` /
`qwen-local` / `gemma-cloud` and 10+ more (see [`praxia/core/llm.py`](../praxia/core/llm.py)).

To run **fully on-prem** with no cloud LLM:

```bash
ollama pull qwen2.5:14b      # default local
ollama pull llama3.3:70b     # or Llama 3.3
ollama pull gemma2:9b        # or Gemma
ollama pull phi3.5:3.8b      # or Phi (small footprint)

praxia run sales --model qwen-local --customer-name "Acme" --product "BizFlow"
# also works: --model llama-local / gemma / phi
```

## 3. Initialize

```bash
praxia init --user-id alice --backend json --model auto
```

This creates `.praxia/` with personal memory storage, registers the 6 default
business skills with the org registry, and bootstraps an admin user.

## 3a. First login (read this once)

`praxia init` creates a single admin user named `admin` and writes its API
key to a one-time file:

```
.praxia/auth/BOOTSTRAP_API_KEY.txt
```

That file is the **only place** the raw key is ever stored. The
`users.jsonl` next to it only keeps the SHA-256 hash. What to do on first
install:

1. Open the file, copy the API key (`r19Kf88…` 43-character string).
2. Save it somewhere safe (password manager / secret store).
3. Delete `BOOTSTRAP_API_KEY.txt` — leaving it on disk is a credential
   leak.

### Logging in

| Scenario | What you enter on the `praxia ui` login screen |
|---|---|
| **Single-user dev** (`.praxia/auth/users.jsonl` empty / not present) | any User ID — instant pass-through, all features unlocked |
| **You ran `praxia init`** (the bootstrap admin is the only user) | User ID: `admin` · Password: the API key from `BOOTSTRAP_API_KEY.txt` |
| **Multi-user prod** (admin has created more users via `praxia user create alice …` or the Admin → Users tab) | User ID: that username · Password: API key issued when the user was created (shown once, then hashed) |
| **SSO** (`PRAXIA_SSO_PROVIDER` set) | "Sign in with \<provider\>" button above the API-key form |

### Adding more users

After logging in as `admin`:

- **UI**: Admin → Users → Create — fill username / role / email → success
  toast shows the new user's API key once, copy it then dismiss.
- **CLI**: `praxia user create alice --role member` — prints the key to
  stdout, same one-shot rule.

### Lost the bootstrap key?

```bash
rm -rf .praxia/auth        # wipe the auth store
praxia init                # re-bootstraps a fresh admin + new key
```

This is destructive (deletes every existing user record), so do it only
for a brand-new install. For production, use `praxia user rotate-key
<user>` instead.

## 4. Run a flow

Three pre-built multi-agent flows ship with Praxia:

```bash
# B2B sales preparation — IR / minutes / RAG → hypotheses → FAQ → proposal
praxia run sales --customer-name "Acme Corp" --product "BizFlow"

# Long-document logical-consistency review (3-agent crew)
praxia run logic --document spec.pdf       # auto-parses .pdf / .docx / .pptx / .xlsx / .csv

# Self-correcting RAG — query expansion → eval → hallucination check loop
praxia run rag --question "Which license is Praxia released under?"
```

## 4½. Let the LLM drive — autonomous agent

For tasks where you don't want to hand-orchestrate flows, use
`praxia.agent.AutonomousAgent`. It runs a LLM-driven tool-use
loop over personal/org memory, the frozen layer, business skills, and
external connectors — the LLM decides which tools to call and when.

```bash
# CLI — one-liner
praxia agent run "Tell me what we know about Acme and draft a proposal" \
    --user-id alice --org-id acme --max-steps 10

# List the 11 built-in tools
praxia agent tools
```

```python
# SDK
from praxia.agent import AutonomousAgent
from praxia.core.llm import LLM

agent = AutonomousAgent(user_id="alice", org_id="acme", llm=LLM("claude"))
result = agent.run("Tell me what we know about Acme and draft a proposal.")
print(result.final_text)
for tc in result.tool_calls:
    print(f"- {tc.name}({tc.arguments_text[:60]}) ok={tc.ok}")
```

Every tool call is **audit-logged** and `pull_from_connector` is
**ACL-checked**. `record_fact` is a no-op when memory mode is `read_only`.
See [FEATURES § 38](FEATURES.md#38-autonomous-agent-llm-driven-tool-use-loop)
for the full tool catalog and governance details.

## 5. Run a single business skill

Six domain-tuned skills with built-in guardrails:

```bash
praxia skill run investment "3-year thesis on a hypothetical mid-cap issuer"
praxia skill run sales      "Plan an outreach to Acme Corp (manufacturing)"
praxia skill run design     "Review the architecture in spec.md"
praxia skill run purchasing "Compare 5 supplier RFQs from suppliers.csv"
praxia skill run patent     "Prior-art search: solid-state battery design"
praxia skill run legal      "Review the risks in services_agreement.pdf"
```

Plus four utility skills always available:

```bash
# Prompt template designer (text → polished system+user template + few-shot)
praxia skill run prompt_designer "Score contract risk 1-5 in JSON"

# Output exporter — natural-language hint → MD / HTML / PPTX / DOCX bytes
praxia skill run output_format "Export the latest report as a Word document"

# Code-gen designers (Claude-Skills-style) — LLM authors python-pptx /
# python-docx code in a sandbox, returns design-rich .pptx / .docx bytes
# with theme applied (colors / fonts / logo / footer from .praxia/themes/).
praxia skill run pptx_designer "Q4 sales review for Acme — cover, summary, top 3 customers, 2x2 challenges, next actions. 10 slides."
praxia skill run docx_designer "Vendor onboarding checklist — 3 sections, table of required docs, callout for legal review."
```

## 6. Launch the UI

```bash
praxia ui --port 8501
# Open http://localhost:8501
```

### Sign-in

The UI opens on a login screen:

- **Single-user dev mode** (no users created via CLI yet): just type any User ID and click Sign in. You get unrestricted access. Suitable for laptop / trusted-LAN.
- **Multi-user mode** (after `praxia user create alice --role admin` issues at least one user): User ID + Password (the API key issued at user-create time). Sign-in resolves to that user's role.
- **SSO mode**: when `PRAXIA_SSO_PROVIDER` is configured, the login form shows a primary "Sign in with \<provider\>" button (Google / Microsoft Entra / Okta / GitHub / Keycloak / generic OIDC) above the API-key form. Persistent login: a SameSite=Lax cookie + server-side session record at `.praxia/sessions/<token>.json` (30-min sliding TTL) keeps the user logged in across browser reloads.

For pure HTTP / non-Streamlit consumers there's also `praxia serve` (FastAPI + OIDC SSO).

### Layout

A fixed top-bar nav (Run / Prompts / Data / Knowledge / Dashboard / Preferences, plus Admin for admin role), a sidebar dedicated to the **Context picker** (which folders / memory layers feed the current run), and a workspace per view. Top nav stays pinned to the viewport top, chat input pinned to the bottom — only the message area scrolls in between (ChatGPT-style).

| View | What's there |
|------|------|
| **🎬 Run** | Two sub-tabs. **🤖 Agent** = chat interface backed by `AutonomousAgent`; goal in, agent picks tools (search, connectors, skills) and iterates. **Image attachments** supported (vision-capable models) — use the 📎 button on the chat input to attach PNG/JPG/GIF/WebP. **Persistent threads**: every conversation is stored at `.praxia/chats/<user>/<id>.json` and listed in the `💬 Conversations` popover so users can resume, rename, or delete past threads. Ephemeral checkbox keeps the conversation in session memory only (no disk writes). **🛠 Skill** = pick a business skill (investment / sales / design / purchasing / patent / legal), submit input, get one answer. Selected Context folders feed both via grep-relevance filter on large folders. |
| **📝 Prompts** | Three sub-tabs: Generate (PromptDesigner — task in, polished template back), Browse & edit (CRUD on your prompt library), Distribute (admin only — push curated prompts to specific users / roles). |
| **📁 Data** | Manage data folders. Local folders = files you upload here, including images (PNG/JPG/GIF/WebP) which the built-in `ImageParser` makes first-class scope content. **Folders can be shared read-only with other users** via the Share section (multiselect from the auth UserStore — owner can upload + delete + reshare, sharees can only read). Connector folders = registered external paths (Box / SharePoint / Notion / etc.). |
| **🧠 Knowledge** | Browse personal + shared memory entries, plus the Skill registry (your skills + org-promoted ones). |
| **📊 Dashboard** | Three KPIs + horizontal bar charts. Personal: total runs, success rate, memory entries. Org: active users, org runs, success rate. |
| **👤 Preferences** | Per-user persistent settings: language, color theme (auto/light/dark). Saved to `.praxia/preferences/<user>.json`. |
| **⚙ Admin** | Admin role only. Seven sub-tabs: **Settings** (default LLM model — persistent across users/sessions, picker is provider→model two-step with per-provider Custom-deployment input · Memory policy with `single` / `composite` / `routed` strategy — composite fans reads out across N backends + RRF/union/intersection/weighted/llm_rerank fusion, routed picks per-query via rule-based regex or LLM router · persistent KNOWN_KEYS grouped per provider — `LLM · OpenAI`, `LLM · Azure OpenAI`, `LLM · AWS Bedrock`, `LLM · Vertex AI`, `LLM · Azure AI Foundry`, `LLM · Anthropic`, `LLM · Google`, `LLM · DeepSeek`, `LLM · Mistral`, etc. — set values masked as `****` with no partial leak, per-row `🗑 Delete` removes from `.praxia/config.toml`), Users, Connectors, Policies (ACL), Consolidate (sleep-time promotion), Exports (CSV/JSON/JSONL), About. |

## 7. Multi-LTM fusion + dynamic routing (optional, accuracy boost)

Different LTMs are good at different things — entity linking (Mem0),
temporal KG (Zep), audit trail (JSON), vector recall (HindSight). You can
run several at once and either fuse the results or pick per-query.

```python
from praxia.memory.composite import CompositeBackend, WeightedBackend
from praxia.memory.backends import load_backend
from praxia import PersonalMemory

# A. Parallel fan-out + Reciprocal Rank Fusion
composite = CompositeBackend(
    backends=[
        WeightedBackend("mem0",      load_backend("mem0"),      weight=1.5),
        WeightedBackend("zep",       load_backend("zep"),       weight=1.0),
        WeightedBackend("hindsight", load_backend("hindsight"), weight=1.0),
    ],
    fusion="rrf",       # rrf | union | intersection | weighted | llm_rerank
    write_to="mem0",    # writes go here only; reads fan-out
)
pm = PersonalMemory(user_id="alice", backend=composite)
```

```python
# B. Dynamic routing — query-aware backend selection
from praxia.memory.router import RoutedBackend, RuleRouter

routed = RoutedBackend(
    backends={
        "mem0":      load_backend("mem0"),
        "zep":       load_backend("zep"),
        "hindsight": load_backend("hindsight"),
        "json":      load_backend("json"),
    },
    router=RuleRouter(),   # or LLMRouter(llm=praxia.llm) for LLM-classified routes
    write_to="mem0",
)
pm = PersonalMemory(user_id="alice", backend=routed)
```

The rule router auto-detects English **and** Japanese keywords:
temporal (`last week` / `先月`) → Zep, audit (`changelog` / `履歴`) → JSON,
entity (`who is` / `について`) → Mem0, similarity (`類似`) → HindSight.

See [FEATURES.md § 5.1](FEATURES.md#51-multi-ltm-fusion--dynamic-routing-accuracy-boost) for the full strategy table and tradeoffs.

## 8. Personal-to-org memory distillation

Run the nightly batch that promotes effective patterns from individual
memory to organizational blocks:

```bash
praxia consolidate --dry-run                 # preview what would be promoted
praxia consolidate --threshold 0.75          # production threshold
praxia freeze --block team_norms             # freeze a stable block to git-tracked Markdown
```

## 8a. Production-grade OAuth + KMS encryption

For multi-worker / multi-host deployments, run the FastAPI server and configure a KMS adapter:

```bash
# Install with server + KMS extras
pip install "praxia[server,kms-aws]"   # or kms-azure / kms-gcp / kms-vault

# Pin the public URL so the redirect URI is stable
export PRAXIA_PUBLIC_URL=https://praxia.example.com

# Switch to KMS-backed envelope encryption
export PRAXIA_KMS_ADAPTER=aws
export PRAXIA_KMS_KEY_ID=arn:aws:kms:us-east-1:111122223333:key/...

praxia serve --host 0.0.0.0 --port 8000
```

OAuth endpoints exposed under `/api/v1/oauth/{provider}/`:
- `POST /start` — build authorization URL for current user
- `GET /callback` — handle IdP redirect, exchange code, save token
- `GET /status` — token presence + expiry
- `DELETE` — revoke locally

State is shared across workers via a TTL-pruned JSON file, so the redirect can land on any replica.

## 8b. A/B experiments

```bash
# Define an experiment (DRAFT)
praxia experiment create proposal_v2 \
    --name "Proposal: shorter vs longer prompt" \
    --variants '{"control":{"prompt":"<800-word>"},"candidate":{"prompt":"<400-word>"}}' \
    --traffic-split "control=0.5,candidate=0.5"

# Activate
praxia experiment start proposal_v2

# Inspect results once enough outcomes are recorded
praxia experiment results proposal_v2
# → 🏆 Tentative winner: candidate (confidence 0.41)
```

In your skill / flow, retrieve the variant for the current user:

```python
from praxia.experiments import ExperimentRegistry

reg = ExperimentRegistry()
variant = reg.assign("proposal_v2", user_id="alice", role="member")
prompt = variant.payload["prompt"] if variant else default_prompt
```

The same user always sees the same variant during the experiment (SHA-256 bucket). Outcomes are recorded via `record_outcome()` and rolled up per variant.

## 8c. LLM output quality evaluation

```bash
# Skipped by default (requires real API keys + costs tokens)
pytest tests/llm_eval -m llm_eval -v

# Update baselines after a known-good change
pytest tests/llm_eval --update-baselines

# Compare a different model on the same cases
pytest tests/llm_eval --llm-eval-model gpt-4o
```

Each PR is graded against a committed baseline; a > 5pt score drop fails CI. See [docs/EVALUATION.md](EVALUATION.md).

## 9. Per-user OAuth (recommended for enterprise)

Each Praxia user authorizes external systems with **their own credentials** —
the external system's native ACL is enforced per-user.

```bash
# Once: register OAuth apps and add client credentials to .env
PRAXIA_OAUTH_BOX_CLIENT_ID=...
PRAXIA_OAUTH_BOX_CLIENT_SECRET=...

# Per user: authorize once
praxia oauth start box --user-id alice
# Open the URL → log in to Box → token saved encrypted

# From now on, alice's connector calls use her token
praxia connector pull box 0 --user-id alice
```

Supported providers: Box, Microsoft (SharePoint/OneDrive), Dropbox,
Google Drive, Salesforce. See [PLUGINS.md](PLUGINS.md) to add more.

## 10. Admin operations

```bash
# User management (audited)
praxia user create alice --role member
praxia user update alice --role operator --email alice@a.test
praxia user audit --limit 100

# Resource access policies (for IS departments)
praxia policy add deny connector "box:/Confidential/*" \
    --principals "role:member,role:viewer" \
    --description "Block Confidential folder for non-operators"
praxia policy test alice member connector box:/Confidential/q3.pdf read

# Data exports (chain-of-custody — every export self-audits)
praxia admin export-audit audit.csv --since-days 30
praxia admin export-users users.json --format json
praxia admin export-memory ./backup --all
```

## 11. Discover what's available

```bash
praxia list flows         # available multi-agent flows
praxia list skills        # 6 business-domain skills
praxia list models        # supported LLM aliases
praxia list backends      # memory backends
praxia connector list     # external connectors
```

---

## Troubleshooting

**"No LLM provider key found"** → run `praxia config init` and add at least
one of `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` / `GEMINI_API_KEY` /
`DASHSCOPE_API_KEY`, or use `qwen-local` with Ollama running.

**File parsing fails** → install the office extra: `pip install "praxia[office]"`.

**Audio input/output silent** → install `praxia[audio]` and ensure your
LLM provider key is set (Whisper / OpenAI TTS reuse `OPENAI_API_KEY`).

**OAuth flow fails with "Unknown state"** → the state cache is in-memory.
For production, replace the in-memory state store with Redis / DB; see
[FEATURES.md § 25](FEATURES.md#25-user-delegated-oauth-per-user-external-system-access).

For more, see [docs/FEATURES.md](FEATURES.md), [docs/PLUGINS.md](PLUGINS.md),
or open an issue at <https://github.com/praxia-dev/praxia/issues>.
