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¶
- Group related research - Use one workspace per project
- Enable indexing - For workspaces you'll query later
- Use descriptive names - Easy identification
- Tag consistently - For filtering and organization
- Archive when done - Save storage costs