Skip to content

Workspaces

Workspaces organize graph executions and their artifacts into logical groups for research projects.

Overview

graph TB
    subgraph "Workspace"
        MANIFEST[WorkspaceManifest]

        subgraph "Jobs"
            J1[Graph Job 1]
            J2[Graph Job 2]
            J3[Graph Job 3]
        end

        subgraph "Artifacts"
            RESULTS[results/]
            SCREENSHOTS[screenshots/]
            REPORTS[reports/]
        end

        subgraph "Index"
            I1[Indexed PDFs]
            I2[Indexed Markdown]
            I3[Semantic Search]
        end
    end

    MANIFEST --> Jobs
    MANIFEST --> Artifacts
    MANIFEST --> Index

    J1 -->|produces| RESULTS
    J2 -->|produces| SCREENSHOTS
    RESULTS -->|indexed into| I1

Key Concepts

Concept Description
Workspace Container for related research
Manifest Workspace metadata and configuration
Artifacts Files produced by graph executions
Runs Individual graph execution records
Index Optional semantic search over artifacts

Documentation

Document Description
Artifacts Artifact types and tracking
Runs Run manifests and history

WorkspaceManager

Main interface for workspace operations.

from cbintel.workspace import WorkspaceManager, WorkspaceConfig

manager = WorkspaceManager()

# Create workspace
config = WorkspaceConfig(
    name="Opposition Research",
    description="Research on political opponents",
    index_enabled=True,
)
workspace = await manager.create(config)
print(f"Workspace ID: {workspace.workspace_id}")

# List workspaces
workspaces = await manager.list()
for ws in workspaces:
    print(f"{ws.name}: {ws.artifact_count} artifacts")

# Get workspace
workspace = await manager.get("ws_abc123")

# Delete workspace
await manager.delete("ws_abc123")

Storage Layout

files.nominate.ai/cbintel-jobs/
└── workspaces/
    └── {workspace_id}/
        ├── manifest.json           # Workspace metadata
        ├── runs/
        │   └── {run_id}/
        │       ├── manifest.json   # Run metadata
        │       ├── result.json     # Graph result
        │       ├── report.md       # Generated report
        │       └── artifacts/
        │           ├── screenshots/
        │           └── data/
        └── outputs/
            └── {aggregated reports}

Creating Workspaces

Basic Workspace

config = WorkspaceConfig(
    name="Q1 Research",
    description="Research for Q1 2024",
)
workspace = await manager.create(config)

With Indexing

config = WorkspaceConfig(
    name="Indexed Research",
    index_enabled=True,  # Enable semantic search
)
workspace = await manager.create(config)

With Tags

config = WorkspaceConfig(
    name="Campaign Research",
    tags=["campaign", "2024", "primary"],
)
workspace = await manager.create(config)

Workspace Manifest

{
  "workspace_id": "ws_abc123",
  "name": "Opposition Research",
  "description": "Research on political opponents",
  "created_at": "2024-01-15T10:00:00Z",
  "updated_at": "2024-01-20T15:30:00Z",
  "config": {
    "index_enabled": true
  },
  "tags": ["campaign", "opposition"],
  "runs_count": 5,
  "artifact_count": 47,
  "total_size_bytes": 125000000,
  "index_workspace_id": "idx_xyz789"
}

Running Graphs in Workspaces

Via API

curl -X POST https://intel.nominate.ai/api/v1/jobs/graph \
  -H "Content-Type: application/json" \
  -d '{
    "template": "deep_research",
    "params": {"query": "John Smith"},
    "workspace_id": "ws_abc123"
  }'

Via Python

from cbintel.client import JobsClient

client = JobsClient()

job = await client.submit("graph", {
    "template": "deep_research",
    "params": {"query": "John Smith"},
    "workspace_id": "ws_abc123",
})

Artifacts are Auto-Stored

When a graph runs in a workspace: 1. Run manifest is created 2. Result is stored 3. Report is generated 4. Screenshots/data are organized 5. Content is indexed (if enabled)

Querying Workspaces

List Runs

workspace = await manager.get("ws_abc123")
runs = await workspace.list_runs()

for run in runs:
    print(f"Run {run.run_id}: {run.status}")
    print(f"  Graph: {run.graph_name}")
    print(f"  Duration: {run.duration_seconds}s")

Get Artifacts

artifacts = await workspace.list_artifacts()

for artifact in artifacts:
    print(f"{artifact.path}: {artifact.size_bytes} bytes")
    print(f"  Type: {artifact.artifact_type}")

Semantic Search (Indexed Workspaces)

from cbintel.index import IndexClient

index = IndexClient()

# Query across all workspace content
results = await index.query(
    workspace.index_workspace_id,
    "What is the subject's stance on healthcare?"
)

for result in results:
    print(f"Source: {result.source}")
    print(f"Content: {result.text}")

Index Integration

When index_enabled=True, workspace content is indexed for semantic search.

Automatic Indexing

  • PDF reports are indexed
  • Markdown content is indexed
  • Synthesized text is indexed

Manual Indexing

from cbintel.index import IndexClient

index = IndexClient()

# Index a PDF
await index.index_pdf(
    workspace.index_workspace_id,
    file_url="https://files.nominate.ai/.../report.pdf"
)

# Index markdown
await index.index_markdown(
    workspace.index_workspace_id,
    content="# Research findings...",
    title="Weekly Briefing"
)

Workspace Lifecycle

stateDiagram-v2
    [*] --> Created: create()
    Created --> Active: add runs/artifacts
    Active --> Active: query/search
    Active --> Archived: archive()
    Archived --> Active: unarchive()
    Active --> [*]: delete()
    Archived --> [*]: delete()

Archiving

# Archive workspace (reduces storage, keeps metadata)
await manager.archive("ws_abc123")

# Unarchive
await manager.unarchive("ws_abc123")

Configuration

Environment Variables

# Storage
WORKSPACE_STORAGE_URL=https://files.nominate.ai
WORKSPACE_STORAGE_BUCKET=cbintel-jobs

# Indexing
INDEX_API_URL=https://index.nominate.ai
INDEX_ENABLED=true

Best Practices

  1. Group related research - Use one workspace per project
  2. Enable indexing - For workspaces you'll query later
  3. Use descriptive names - Easy identification
  4. Tag consistently - For filtering and organization
  5. Archive when done - Save storage costs