Metadata-Version: 2.4
Name: novalab-adk
Version: 1.3.0
Summary: NovaLab Agent Development Kit — Build, test, and deploy Nova AI agents with multi-agent orchestration
License-Expression: MIT
Keywords: adk,agents,ai,multi-agent,novalab,orchestration,parallel,pipeline,routing,workflows
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27.0
Requires-Dist: pydantic>=2.0.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: ruff>=0.4.0; extra == 'dev'
Description-Content-Type: text/markdown

# Nova ADK — Agent Development Kit

The official Agent Development Kit for the [NovaLab](https://novalab.build) AI orchestration platform. Build, test, and deploy autonomous AI agents with enterprise-grade trust, confidence scoring, and full auditability.

**Any LLM in. Governed agents out.**

Available in **TypeScript** (`@novalabai/adk`) and **Python** (`novalab-adk`).

> **v1.1.0** — New `nova.orchestrate` module: `route(intent)`, `parallel([agent₁, agent₂])`, `verify(output)`, and composable `pipeline()`.

---

## Table of Contents

- [Features](#features)
- [Prerequisites](#prerequisites)
- [Installation](#installation)
- [API Keys Setup](#api-keys-setup)
- [Quick Start](#quick-start)
- [Running the Playground Server](#running-the-playground-server)
- [Testing Your Setup](#testing-your-setup)
- [Writing an Agent](#writing-an-agent)
- [Deploying an Agent](#deploying-an-agent)
- [Running an Agent](#running-an-agent)
- [Smart Model Routing](#smart-model-routing)
- [Confidence Layer](#confidence-layer)
- [Multi-Agent Orchestration](#multi-agent-orchestration)
  - [route(intent)](#routeintent)
  - [parallel(\[agent₁, agent₂\])](#parallelagent₁-agent₂)
  - [verify(output)](#verifyoutput)
  - [pipeline()](#pipeline)
- [Multi-Agent Architecture](#multi-agent-architecture)
- [Workflows](#workflows)
- [Signal Monitoring](#signal-monitoring)
- [Automations](#automations)
- [Webhooks](#webhooks)
- [Connections Hub](#connections-hub)
- [API Resources](#api-resources)
- [Project Structure](#project-structure)
- [Running Tests](#running-tests)
- [Deployment Models](#deployment-models)
- [Compliance](#compliance)
- [Troubleshooting](#troubleshooting)
- [License](#license)

---

## Features

- **Agent Management** — Create, configure, deploy, and run AI agents programmatically
- **Multi-Agent Orchestration** — `route(intent)`, `parallel([agent₁, agent₂])`, `verify(output)` as first-class SDK primitives
- **Composable Pipelines** — Chain route → parallel → verify into a single `pipeline()` call
- **Smart Model Routing** — Automatically routes tasks to Claude (analytical) or Gemini (creative) based on intent
- **Workflow Studio** — Build multi-step agent pipelines with confidence gates at every step
- **Signal Monitor** — Ingest and stream real-time telemetry from IoT, vehicles, machines, and infrastructure
- **Automations** — Rule-based workflows described in plain English with configurable confidence thresholds
- **Connections Hub** — Manage third-party integrations (CRM, Slack, GitHub, databases, MQTT, etc.)
- **Data Explorer** — Upload datasets and query them with natural language
- **History & Replay** — Full audit trail with decision explanations
- **Webhook Support** — 8+ event types with HMAC-SHA256 signed payloads
- **Confidence Layer** — Every decision carries a 0-100% score determining autonomy level
- **Human-in-the-Loop** — High-risk actions require explicit human approval
- **EU-first** — GDPR-native, EU AI Act-ready

---

## Prerequisites

- **Node.js** >= 18 (for TypeScript SDK)
- **Python** >= 3.10 (for Python SDK and playground server)
- **npm** or **yarn** (for TypeScript)
- **pip** (for Python)

---

## Installation

### TypeScript SDK

```bash
npm install @novalabai/adk
```

Or install from source:

```bash
cd Nova/typescript
npm install
npm run build
```

Then in your project:

```bash
npm install /path/to/Nova/typescript
```

### Python SDK

```bash
pip install novalab-adk
```

Or install from source:

```bash
cd Nova/python
pip install -e .
```

### Playground Server Dependencies

The playground server requires these Python packages:

```bash
pip install httpx fastapi uvicorn python-dotenv
```

---

## API Keys Setup

Nova uses **Claude (Anthropic)** for analytical tasks and **Gemini (Google)** for creative tasks. You need API keys for both.

### Get Your Keys

1. **Anthropic API Key** — Sign up at [console.anthropic.com](https://console.anthropic.com) and create an API key (starts with `sk-ant-...`)
2. **Google Gemini API Key** — Get one at [aistudio.google.com](https://aistudio.google.com/apikey) (starts with `AIza...`)

### Configure Keys

**Option A: `.env` file (recommended)**

Create a `.env` file in the project root:

```bash
ANTHROPIC_API_KEY="sk-ant-your-key-here"
GEMINI_API_KEY="AIzaSy-your-key-here"
```

The server auto-loads this file using `python-dotenv`.

**Option B: Environment variables**

```bash
export ANTHROPIC_API_KEY="sk-ant-your-key-here"
export GEMINI_API_KEY="AIzaSy-your-key-here"
```

> **Security:** The `.env` file is listed in `.gitignore` and will not be committed to version control. Never hardcode API keys in source files.

---

## Quick Start

### 1. Start the Server

```bash
cd Nova
python3 playground/real_server.py
```

You should see:

```
╔══════════════════════════════════════════════════════════════╗
║        Nova ADK — Real AI Server (Claude + Gemini)         ║
╠══════════════════════════════════════════════════════════════╣
║  API:     http://localhost:4300/v1                          ║
║  Docs:    http://localhost:4300/docs                        ║
║                                                              ║
║  Claude:  Connected                                          ║
║  Gemini:  Connected                                          ║
╚══════════════════════════════════════════════════════════════╝
```

### 2. Test with curl

```bash
# Health check — verify API keys are loaded
curl http://localhost:4300/v1/health

# Create an agent
curl -X POST http://localhost:4300/v1/agents \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"name": "My Agent", "description": "A test agent"}'

# Deploy the agent
curl -X POST http://localhost:4300/v1/agents/AGENT_ID/deploy \
  -H "Authorization: Bearer your-api-key"

# Run the agent
curl -X POST http://localhost:4300/v1/agents/AGENT_ID/run \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"input": "Analyze the security risks of using JWT tokens"}'
```

### 3. Run the Full Demo

```bash
# In a second terminal
PYTHONPATH=python python3 playground/real_demo.py
```

This sends 5 different task types and shows you the full routing pipeline in action.

---

## Running the Playground Server

Nova includes three server options:

| Server | Port | Description |
|--------|------|-------------|
| `playground/real_server.py` | 4300 | **Real AI** — Calls Claude + Gemini APIs |
| `playground/mock_server.py` | 4200 | **Mock** — Simulated responses (no API keys needed) |
| `playground/mock-server.ts` | 4100 | **Mock (TS)** — TypeScript mock server |

### Real AI Server (recommended)

```bash
python3 playground/real_server.py
```

Requires API keys in `.env`. Routes tasks to Claude or Gemini based on intent.

### Mock Server (for development)

```bash
# Python mock
python3 playground/mock_server.py

# TypeScript mock
npx tsx playground/mock-server.ts
```

No API keys needed — returns simulated responses for testing SDK features.

---

## Testing Your Setup

### Health Check

```bash
curl http://localhost:4300/v1/health
```

Expected response:

```json
{
  "status": "ok",
  "version": "1.0.0-real",
  "models": {
    "claude": "connected",
    "gemini": "connected"
  }
}
```

If you see `"no API key"` for either model, check your `.env` file.

### Run Demo Scripts

```bash
# Real AI demo (requires real_server.py running on port 4300)
PYTHONPATH=python python3 playground/real_demo.py

# Mock demo — Python (requires mock_server.py running on port 4200)
PYTHONPATH=python python3 playground/demo.py

# Mock demo — TypeScript (requires mock-server.ts running on port 4100)
npx tsx playground/demo.ts
```

### Run Unit Tests

```bash
# Python SDK tests
cd python && pytest tests/

# TypeScript SDK tests
cd typescript && npm test
```

---

## Writing an Agent

### TypeScript

```typescript
import { NovaClient } from "@novalabai/adk";

const nova = new NovaClient({
  apiKey: process.env.NOVA_API_KEY,
  region: "eu-west-1",
});

// Create an agent with confidence thresholds and tools
const agent = await nova.agents.create({
  name: "Risk Analyser",
  description: "Analyses portfolio risk using financial data",
  model: "claude",
  tools: [
    { name: "portfolio_reader", permissions: ["data:read"], riskLevel: "low" },
    { name: "market_data", permissions: ["data:read"], riskLevel: "low" },
  ],
  confidenceThresholds: {
    autonomous: 90,    // >= 90% — runs without intervention
    notify: 70,        // >= 70% — runs and notifies stakeholders
    approvalRequired: 50,  // >= 50% — waits for human approval
    // < 50% — blocked entirely
  },
  humanApproval: {
    required: true,
    riskThreshold: "high",
  },
});

console.log(`Agent created: ${agent.id}`);
```

### Python

```python
import asyncio
from novalab_adk import NovaClient

async def main():
    async with NovaClient(api_key="...", region="eu-west-1") as nova:
        agent = await nova.agents.create(
            name="Risk Analyser",
            description="Analyses portfolio risk using financial data",
            model="claude",
            tools=[
                {"name": "portfolio_reader", "permissions": ["data:read"], "risk_level": "low"},
                {"name": "market_data", "permissions": ["data:read"], "risk_level": "low"},
            ],
            confidence_thresholds={
                "autonomous": 90,
                "notify": 70,
                "approval_required": 50,
            },
            human_approval={"required": True, "risk_threshold": "high"},
        )
        print(f"Agent created: {agent.id}")

asyncio.run(main())
```

### Using the REST API Directly

```bash
curl -X POST http://localhost:4300/v1/agents \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Risk Analyser",
    "description": "Analyses portfolio risk",
    "model": "claude",
    "confidenceThresholds": {
      "autonomous": 90,
      "notify": 70,
      "approvalRequired": 50
    }
  }'
```

---

## Deploying an Agent

After creating an agent, deploy it to make it active:

### TypeScript

```typescript
await nova.agents.deploy(agent.id);
console.log("Agent deployed and active");
```

### Python

```python
await nova.agents.deploy(agent.id)
print("Agent deployed and active")
```

### REST API

```bash
curl -X POST http://localhost:4300/v1/agents/AGENT_ID/deploy \
  -H "Authorization: Bearer your-api-key"
```

---

## Running an Agent

Once deployed, send tasks to your agent:

### TypeScript

```typescript
const result = await nova.agents.run(agent.id, {
  input: "Analyse portfolio risk for Q1 2026",
  context: { portfolio: "growth-fund-a" },
});

console.log(`Output:     ${result.output}`);
console.log(`Confidence: ${result.confidence}%`);
console.log(`Model:      ${result.model_used}`);
console.log(`Autonomy:   ${result.autonomy_level}`);
console.log(`Audit ID:   ${result.audit_id}`);
```

### Python

```python
result = await nova.agents.run(
    agent.id,
    input="Analyse portfolio risk for Q1 2026",
    context={"portfolio": "growth-fund-a"},
)

print(f"Output:     {result.output}")
print(f"Confidence: {result.confidence}%")
print(f"Model:      {result.model_used}")
print(f"Autonomy:   {result.autonomy_level}")
print(f"Audit ID:   {result.audit_id}")
```

### REST API

```bash
curl -X POST http://localhost:4300/v1/agents/AGENT_ID/run \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"input": "Analyse portfolio risk for Q1 2026", "context": {"portfolio": "growth-fund-a"}}'
```

### Agent Run Response

```json
{
  "output": "Based on current market analysis...",
  "confidence": 92,
  "agents_involved": ["nova-intent", "nova-research", "nova-guard", "nova-verify", "nova-confidence"],
  "audit_id": "audit-a1b2c3d4",
  "duration": 1250,
  "model_used": "claude-sonnet-4-20250514",
  "routing": {
    "category": "analytical",
    "recommended_model": "claude",
    "claude_score": 3,
    "gemini_score": 0,
    "reasoning": "Task contains analytical keywords. Routing to Claude for precise reasoning."
  },
  "risk": {
    "risk_level": "low",
    "requires_approval": false
  },
  "autonomy_level": "AUTONOMOUS",
  "tokens_used": 450
}
```

---

## Smart Model Routing

Nova automatically routes tasks to the best model based on intent classification:

| Model | Routed For | Keywords |
|-------|-----------|----------|
| **Claude** (Anthropic) | Reasoning, analysis, code, security, logic | analyse, reason, code, debug, security, evaluate, compare, technical, algorithm |
| **Gemini** (Google) | Creative writing, summarisation, content | create, write, draft, summarise, story, brainstorm, translate, blog, marketing |

When scores are equal, Nova defaults to **Claude** for safer, more precise output.

### Examples

| Task | Routed To | Why |
|------|-----------|-----|
| "Analyze security risks of JWT tokens" | Claude | Contains "analyze", "security", "risk" |
| "Write a blog post about AI trends" | Gemini | Contains "write", "blog", "content" |
| "Review this code for bugs" | Claude | Contains "review", "code" |
| "Create a marketing tagline" | Gemini | Contains "create", "marketing" |
| "What is the best approach?" | Claude | Ambiguous — defaults to Claude |

---

## Confidence Layer

Every Nova decision carries a confidence score (0-100%) that determines the autonomy level:

| Score | Level | Behaviour |
|-------|-------|-----------|
| 90-100% | `AUTONOMOUS` | Executes without intervention |
| 70-89% | `NOTIFY` | Executes and notifies stakeholders |
| 50-69% | `APPROVAL_REQUIRED` | Blocked until human approves |
| 0-49% | `BLOCKED` | Escalated to human, cannot proceed |

Thresholds are configurable per agent, per workflow, and per organisation.

### Confidence Scoring Factors

- **Routing clarity** — Higher when model selection is clear (large score gap between Claude and Gemini)
- **Risk level** — Reduced for high-risk tasks (delete, deploy, payment, etc.)
- **Response quality** — Boosted for longer, more detailed AI responses

---

## Multi-Agent Orchestration

Nova v1.1 introduces a first-class orchestration engine with three composable primitives that match the Nova architecture:

```
→ route(intent)              — classify & dispatch to the best agent
→ parallel([agent₁, agent₂]) — fan-out to N agents concurrently
→ verify(output) ✓           — trust-layer verification gate
```

Access via `nova.orchestrate.*` in both TypeScript and Python.

---

### route(intent)

Classify the user's intent and route to the best-matching agent.

**TypeScript**

```typescript
const routed = await nova.orchestrate.route({
  input: "Analyse customer churn for Q4",
  targets: [
    { agentId: "support-agent", intents: ["support", "help", "ticket"] },
    { agentId: "crm-agent",     intents: ["customer", "crm", "lead"] },
    { agentId: "data-agent",    intents: ["analyse", "data", "metrics", "report"] },
    { agentId: "risk-agent",    intents: ["risk", "compliance", "audit"] },
  ],
});

console.log(routed.selectedAgentId); // "data-agent"
console.log(routed.intent);          // "analytics"
console.log(routed.routeConfidence); // 75
console.log(routed.scores);          // { "data-agent": 75, "crm-agent": 25, ... }
console.log(routed.result?.output);  // Agent's response
```

**Python**

```python
from novalab_adk import RouteParams, RouteTarget

routed = await nova.orchestrate.route(RouteParams(
    input="Analyse customer churn for Q4",
    targets=[
        RouteTarget(agent_id="support-agent", intents=["support", "help", "ticket"]),
        RouteTarget(agent_id="crm-agent",     intents=["customer", "crm", "lead"]),
        RouteTarget(agent_id="data-agent",    intents=["analyse", "data", "metrics"]),
        RouteTarget(agent_id="risk-agent",    intents=["risk", "compliance", "audit"]),
    ],
))

print(routed.selected_agent_id)  # "data-agent"
print(routed.result.output)       # Agent's response
```

**Options:**

| Param | Type | Description |
|-------|------|-------------|
| `input` | string | User input to classify |
| `targets` | RouteTarget[] | Candidate agents with intent keywords |
| `targets[].weight` | number (0-1) | Optional bias weight for tie-breaking |
| `context` | object | Context forwarded to the selected agent |
| `dryRun` | boolean | Returns classification without executing the agent |

---

### parallel([agent₁, agent₂])

Execute multiple agents concurrently and merge their results.

**TypeScript**

```typescript
const results = await nova.orchestrate.parallel({
  tasks: [
    { agentId: "support-agent", input: "Summarise ticket #1234", label: "summary" },
    { agentId: "crm-agent",     input: "Get customer profile for ticket #1234", label: "profile" },
    { agentId: "data-agent",    input: "Pull usage metrics for this customer", label: "metrics" },
  ],
  merge: "best",          // "all" | "best" | "first" | "custom"
  timeout: 30_000,        // 30s max per task
  confidenceFloor: 50,    // skip results below 50% confidence
});

console.log(`Completed: ${results.successCount}/${results.tasks.length}`);
console.log(`Best result: ${results.merged?.result?.output}`);
console.log(`Wall time: ${results.duration}ms`);

// Access individual task results
for (const task of results.tasks) {
  console.log(`${task.label}: ${task.status} (${task.duration}ms)`);
}
```

**Python**

```python
from novalab_adk import ParallelParams, ParallelTask

results = await nova.orchestrate.parallel(ParallelParams(
    tasks=[
        ParallelTask(agent_id="support-agent", input="Summarise ticket #1234", label="summary"),
        ParallelTask(agent_id="crm-agent",     input="Get customer profile",   label="profile"),
        ParallelTask(agent_id="data-agent",    input="Pull usage metrics",     label="metrics"),
    ],
    merge="best",
    timeout=30,
    confidence_floor=50,
))

print(f"Completed: {results.success_count}/{len(results.tasks)}")
print(f"Best result: {results.merged.result.output}")
```

**Merge strategies:**

| Strategy | Behaviour |
|----------|-----------|
| `all` | Returns all results. `merged` = highest confidence. |
| `best` | Picks the single highest-confidence result. |
| `first` | Picks the first task to complete. |
| `custom` | Provide a `mergeFn` / `merge_fn` callback. |

**Options:**

| Param | Type | Description |
|-------|------|-------------|
| `tasks` | ParallelTask[] | Tasks to run concurrently |
| `tasks[].agentId` | string | Agent to execute |
| `tasks[].input` | string | Task input |
| `tasks[].label` | string | Optional label for identification |
| `merge` | string | Merge strategy (default: `"all"`) |
| `timeout` | number | Max time per task in ms (TS) or seconds (Python). 0 = no limit. |
| `confidenceFloor` | number | Skip results below this confidence (0-100) |
| `mergeFn` | function | Custom merge function (for `merge: "custom"`) |

---

### verify(output)

Pass an agent's output through the Nova trust layer for verification.

**TypeScript**

```typescript
const verified = await nova.orchestrate.verify({
  input: "Summarise Q4 revenue",
  output: agentResult.output,
  agentId: "data-agent",
  threshold: 80,  // must score >= 80 to pass
});

if (verified.passed) {
  console.log(`Verified ✓ (${verified.trust.overallScore}/100)`);
  console.log(verified.output);  // safe to use
} else {
  console.log(`Failed ✗ — ${verified.summary}`);
  console.log("Concerns:", verified.trust.concerns);
}
```

**Python**

```python
from novalab_adk import VerifyParams

verified = await nova.orchestrate.verify(VerifyParams(
    input="Summarise Q4 revenue",
    output=agent_result.output,
    agent_id="data-agent",
    threshold=80,
))

if verified.passed:
    print(f"Verified ✓ ({verified.trust.overall_score}/100)")
else:
    print(f"Failed ✗ — {verified.summary}")
```

**Trust dimensions scored:**

| Dimension | Weight | Description |
|-----------|--------|-------------|
| Accuracy | 30% | Is the output factually correct? |
| Safety | 25% | Does it avoid harmful content? |
| Relevance | 25% | Does it address the original task? |
| Completeness | 20% | Is the response thorough? |

---

### pipeline()

Compose `route → parallel → verify` into a single execution flow.

**TypeScript**

```typescript
const result = await nova.orchestrate.pipeline({
  input: "Analyse customer churn and prepare a retention plan",
  steps: [
    {
      kind: "route",
      params: {
        input: "",  // auto-filled from pipeline input
        targets: [
          { agentId: "data-agent",    intents: ["analyse", "data", "metrics"] },
          { agentId: "support-agent", intents: ["support", "help"] },
        ],
      },
    },
    {
      kind: "parallel",
      params: {
        tasks: [
          { agentId: "data-agent",    input: "Analyse churn rate trends" },
          { agentId: "crm-agent",     input: "Identify at-risk customers" },
        ],
        merge: "best",
      },
    },
    {
      kind: "verify",
      params: { input: "", output: "", threshold: 80 },
    },
  ],
});

console.log(result.output);          // Final verified output
console.log(result.confidence);      // Trust score
console.log(result.verified);        // true/false
console.log(result.agentsInvolved);  // ["data-agent", "crm-agent"]
console.log(result.duration);        // Total wall time (ms)
```

**Python**

```python
from novalab_adk import (
    PipelineStep, PipelineParams,
    RouteParams, RouteTarget,
    ParallelParams, ParallelTask,
    VerifyParams,
)

result = await nova.orchestrate.pipeline(PipelineParams(
    input="Analyse customer churn and prepare a retention plan",
    steps=[
        PipelineStep(kind="route", params=RouteParams(
            input="",
            targets=[
                RouteTarget(agent_id="data-agent", intents=["analyse", "data"]),
                RouteTarget(agent_id="support-agent", intents=["support", "help"]),
            ],
        )),
        PipelineStep(kind="parallel", params=ParallelParams(
            tasks=[
                ParallelTask(agent_id="data-agent", input="Analyse churn trends"),
                ParallelTask(agent_id="crm-agent", input="Identify at-risk customers"),
            ],
            merge="best",
        )),
        PipelineStep(kind="verify", params=VerifyParams(
            input="", output="", threshold=80,
        )),
    ],
))

print(result.output)
print(f"Confidence: {result.confidence}, Verified: {result.verified}")
```

**Pipeline step types:**

| Kind | What it does |
|------|-------------|
| `route` | Classify intent, pick best agent, execute |
| `parallel` | Fan-out N agents, merge results |
| `verify` | Trust-layer verification gate |
| `custom` | Run a custom async handler function |

Each step auto-inherits the previous step's output as input. The final `verify` step gates whether the pipeline passes or fails.

---

## Multi-Agent Architecture

Nova decomposes requests into parallel sub-tasks across specialised internal agents:

```
Request --> Nova-Intent --> Agent Routing --> Parallel Execution --> Nova-Guard --> Nova-Confidence --> Human Gate --> Action --> Audit Log
```

| Agent | Role |
|-------|------|
| **Nova-Intent** | Classifies user intent and routes to appropriate agents |
| **Nova-Research** | Gathers data from connected tools and external sources |
| **Nova-Guard** | Evaluates risk, confidence thresholds, and policy compliance |
| **Nova-Verify** | Cross-checks outputs for accuracy and consistency |
| **Nova-Confidence** | Computes final confidence scores and determines autonomy level |

---

## Workflows

Build multi-step agent pipelines with confidence gates:

```typescript
const workflow = await nova.workflows.create({
  name: "Customer Onboarding",
  steps: [
    { id: "classify", agentId: "nova-intent", action: "classify_request", confidenceGate: 80 },
    { id: "kyc", agentId: "kyc-verifier", action: "verify_identity", confidenceGate: 90 },
    { id: "risk", agentId: "risk-assessor", action: "assess_risk", confidenceGate: 70 },
    { id: "provision", agentId: "account-provisioner", action: "create_account", confidenceGate: 95 },
  ],
});

const result = await nova.workflows.run(workflow.id, { input: { ... } });
```

Each step's output feeds into the next. If any step falls below its confidence gate, the workflow pauses for human review.

---

## Signal Monitoring

Ingest and stream real-time telemetry:

```typescript
// Stream signals from factory equipment
const stream = nova.signals.stream({
  systemIds: ["factory-line-a"],
  signalNames: ["temperature", "vibration"],
  interval: 1000,
});

for await (const signal of stream) {
  console.log(`${signal.name}: ${signal.value} ${signal.unit}`);
}
```

Supported system types: IoT sensors, vehicles, robots, machines, infrastructure (HVAC, power, water).

---

## Automations

Plain-English rule-based workflows:

```typescript
await nova.automations.create({
  name: "High Temperature Alert",
  description: "When temperature > 85C, notify engineering and reduce speed",
  trigger: {
    type: "signal",
    config: { signalName: "temperature", condition: "above", threshold: 85 },
  },
  actions: [
    { type: "notify", config: { connectionId: "slack-eng", message: "Temp alert: {{signal.value}}C" } },
    { type: "agent_run", config: { agentId: "machine-controller", input: "Reduce speed by 20%" } },
  ],
  confidenceThreshold: 80,
});
```

---

## Webhooks

Subscribe to platform events with HMAC-SHA256 verification:

```typescript
import { verifyWebhookSignature } from "@novalabai/adk";

// Available events:
// approval.needed | anomaly.detected | agent.run.completed | agent.run.failed
// workflow.completed | signal.alert | automation.triggered | confidence.low

const isValid = verifyWebhookSignature(payload, signature, secret);
```

---

## Connections Hub

Manage third-party integrations:

| Category | Providers |
|----------|-----------|
| CRM | Salesforce, HubSpot, Pipedrive |
| Communication | Slack, Microsoft Teams, Email |
| Storage | Google Drive, Dropbox, S3 |
| Development | GitHub, GitLab, Jira |
| Data | PostgreSQL, BigQuery, Snowflake |
| IoT / Industrial | MQTT, OPC-UA, custom APIs |

---

## API Resources

Both SDKs provide the same resource structure:

```
nova.agents       — Create, deploy, run, and manage AI agents
nova.orchestrate  — Multi-agent orchestration (route, parallel, verify, pipeline)
nova.workflows    — Build and execute multi-step pipelines
nova.signals      — Ingest and stream real-time telemetry
nova.automations  — Manage rule-based automations
nova.connections  — Third-party integrations
nova.data         — Upload and query datasets
nova.history      — Audit trail and decision replay
nova.trust        — Trust evaluation on any AI output
nova.webhooks     — Event subscriptions
```

---

## Project Structure

```
Nova/
├── .env                        # API keys (not committed to git)
├── .gitignore                  # Excludes .env, node_modules, __pycache__
├── README.md                   # This file
├── package.json                # Root dependencies
│
├── typescript/                 # @novalabai/adk (TypeScript SDK)
│   ├── src/
│   │   ├── index.ts            # Main exports
│   │   ├── client.ts           # NovaClient entry point
│   │   ├── core/               # HTTP client, errors, confidence
│   │   ├── types/              # Full type definitions
│   │   ├── resources/          # API resource classes
│   │   ├── orchestration/      # route, parallel, verify, pipeline
│   │   └── utils/              # HMAC, streaming
│   ├── tests/                  # Vitest unit tests
│   ├── examples/               # Usage examples
│   └── dist/                   # Compiled output
│
├── python/                     # novalab-adk (Python SDK)
│   ├── novalab_adk/
│   │   ├── client.py           # NovaClient entry point
│   │   ├── core/               # HTTP client, errors, confidence
│   │   ├── types/              # Pydantic models
│   │   ├── resources/          # API resource classes
│   │   ├── orchestration/      # route, parallel, verify, pipeline
│   │   └── utils/              # HMAC, streaming
│   ├── tests/                  # Pytest tests
│   └── examples/               # Usage examples
│
└── playground/                 # Local demo servers & scripts
    ├── real_server.py          # Real AI server (Claude + Gemini, port 4300)
    ├── real_demo.py            # Full demo with model routing
    ├── mock_server.py          # Mock server (port 4200)
    ├── mock-server.ts          # Mock server TypeScript (port 4100)
    ├── demo.py                 # Python demo (mock)
    └── demo.ts                 # TypeScript demo (mock)
```

---

## Running Tests

### Python SDK

```bash
cd Nova/python
pip install -e ".[dev]"
pytest tests/
```

Individual test files:

```bash
pytest tests/test_client.py        # Client creation & config
pytest tests/test_confidence.py    # Confidence scoring & gates
pytest tests/test_errors.py        # Error types
pytest tests/test_hmac.py          # Webhook signature verification
pytest tests/test_types.py         # Type validation
```

### TypeScript SDK

```bash
cd Nova/typescript
npm install
npm test
```

---

## Deployment Models

| Model | Description |
|-------|-------------|
| Cloud (SaaS) | Fully managed on EU infrastructure |
| Hybrid | Control plane in cloud, data processing on-premise |
| On-Premise | Full platform in customer infrastructure |
| SDK-only | Embed Nova agents into existing apps via ADK |

---

## Compliance

- GDPR-native — data residency in EU, no cross-border transfers without consent
- EU AI Act-ready — risk classification, transparency obligations, human oversight
- Full audit trail — every decision logged with timestamp, confidence, and reasoning
- Role-based access control — granular permissions per user, team, and agent
- Signed webhooks — HMAC-SHA256 payload verification
- SOC 2 Type II alignment (in progress)

---

## Troubleshooting

### "Claude API key not set" / "Gemini API key not set"

Check that your `.env` file exists in the project root and contains valid keys:

```bash
cat .env
```

Make sure `python-dotenv` is installed:

```bash
pip install python-dotenv
```

### Server won't start

Install required packages:

```bash
pip install httpx fastapi uvicorn python-dotenv
```

### "No such file or directory" when running `python3 playground/real_server.py`

Make sure you're in the `Nova/` directory:

```bash
cd /path/to/Nova
python3 playground/real_server.py
```

### Port already in use

Kill the existing process:

```bash
lsof -ti:4300 | xargs kill -9
```

### Claude/Gemini API errors

- Verify your API keys are valid and active
- Check you have credits/quota on your Anthropic and Google accounts
- Check the health endpoint: `curl http://localhost:4300/v1/health`

---

## License

MIT

---

NovaLab — Build AI Workflows You Can Trust
