Skip to main content

Spring Intelligence API

Spring Intelligence is Flow's AI-powered content research and generation engine. It automates signal discovery, relevance scoring, and content drafting based on your knowledge base and stance.

Overview​

Spring Intelligence helps you:

  1. Discover signals - Monitor RSS feeds, URLs, and semantic searches
  2. Score relevance - AI-powered filtering against your knowledge base
  3. Generate drafts - Platform-specific content from high-relevance signals
  4. Track performance - Analytics on acceptance rate and edit distance

Architecture​

Signal Sources → Ingestion → Relevance Engine → Draft Generation → Review Queue
↓ ↓ ↓ ↓ ↓
RSS/URL Extract Content LLM Scoring Knowledge+Stance Human Review

Authentication​

All endpoints require authentication:

Authorization: Bearer flow_sk_live_abc123...

Knowledge Base​

Your knowledge base defines who you are and what you build. It's used for:

  • Relevance scoring (is this signal relevant to us?)
  • Draft generation (what opinions should we inject?)

Get Knowledge Base​

GET /api/spring/knowledge

Response (Not Configured)

{
"configured": false,
"knowledge": null,
"stance": null
}

Response (Configured)

{
"configured": true,
"knowledge": {
"productName": "Flow Social",
"productTagline": "The zen social media scheduler",
"productDescription": "A calm, beautiful platform for scheduling social posts",
"productFeatures": ["AI content generation", "Multi-platform posting"],
"valuePropositions": ["Save time", "Post consistently"],
"targetAudience": "Content creators and founders",
"idealCustomerProfile": "Solo founders with limited time",
"techStack": ["Cloudflare Workers", "React", "TypeScript"]
},
"stance": {
"hotTakes": ["Serverless is the future", "Quality over quantity"],
"loves": ["Developer experience", "Clean APIs"],
"hates": ["Bloated software", "Complexity for its own sake"],
"contrarianViews": ["Social media should be zen, not stressful"],
"toneKeywords": ["professional", "friendly", "technical"]
}
}

Create/Update Knowledge Base​

PUT /api/spring/knowledge
Content-Type: application/json

{
"productName": "My Product",
"productTagline": "Best product ever",
"productDescription": "A detailed description",
"productFeatures": ["Feature 1", "Feature 2"],
"valuePropositions": ["Value 1", "Value 2"],
"targetAudience": "Developers",
"idealCustomerProfile": "Senior engineers at startups",
"techStack": ["Node.js", "React"]
}

Update Stance Only​

PATCH /api/spring/knowledge/stance
Content-Type: application/json

{
"hotTakes": ["Hot take 1", "Hot take 2"],
"loves": ["Thing we love"],
"hates": ["Thing we hate"],
"contrarianViews": ["Contrarian view"],
"toneKeywords": ["professional", "witty"]
}

Signal Sources​

Configure where Spring looks for content to react to.

List Sources​

GET /api/spring/sources

Response

{
"sources": [
{
"id": "src_abc123",
"type": "rss",
"label": "Hacker News",
"config": { "url": "https://news.ycombinator.com/rss" },
"frequency": "hourly",
"isActive": true,
"lastChecked": 1706000000000
},
{
"id": "src_def456",
"type": "semantic_search",
"label": "Industry Pain Points",
"config": { "query": "social media scheduling problems" },
"frequency": "daily",
"isActive": true
}
],
"count": 2
}

Add Source​

POST /api/spring/sources
Content-Type: application/json

{
"type": "rss",
"label": "TechCrunch",
"config": { "url": "https://techcrunch.com/feed/" },
"frequency": "hourly"
}

Source Types

TypeConfigDescription
rss{ url: string }RSS/Atom feed URL
url{ url: string }Direct webpage URL
semantic_search{ query: string }Semantic search query

Frequencies

  • hourly - Check every hour
  • daily - Check once per day (midnight UTC)
  • weekly - Check once per week (Sunday midnight UTC)

Update Source​

PATCH /api/spring/sources/:id
Content-Type: application/json

{
"label": "Updated Label",
"frequency": "daily",
"isActive": false
}

Delete Source​

DELETE /api/spring/sources/:id

Processed Signals​

Signals are content items discovered from your sources and scored for relevance.

List Signals​

GET /api/spring/signals
GET /api/spring/signals?status=relevant&limit=20

Query Parameters

ParameterTypeDescription
statusstringFilter by status: pending, relevant, discarded, used, expired
limitintegerMax signals to return (default: 50)

Response

{
"signals": [
{
"id": "sig_abc123",
"url": "https://example.com/article",
"title": "Industry News: Major Announcement",
"contentSummary": "Summary of the article...",
"relevanceScore": 85,
"relevanceReasoning": "Directly impacts target audience pain points",
"triggerType": "market_shift",
"status": "relevant",
"discoveredAt": 1706000000000
}
],
"count": 1
}

Relevance Scores

Score RangeMeaningAction
0-50NoiseAuto-discarded
51-79Weak signalLogged but not drafted
80-100High signalProceed to drafting

Trigger Types

TypeDescription
newsGeneral industry news
competitorCompetitor activity or announcement
market_shiftMarket trend or change
user_complaintUser pain point or problem
validationValidates your approach/thesis

Submit URL for Processing​

Manually submit a URL to be processed.

POST /api/spring/signals/submit
Content-Type: application/json

{
"url": "https://example.com/interesting-article",
"title": "Optional title"
}

Response

{
"success": true,
"signalId": "sig_xyz789",
"message": "URL submitted for processing. It will be scored shortly."
}

Update Signal Status​

PATCH /api/spring/signals/:id/status
Content-Type: application/json

{
"status": "used"
}

Draft Generation​

Generate platform-specific content from a signal.

Generate Draft​

POST /api/spring/signals/:id/draft

Response

{
"success": true,
"signal": {
"id": "sig_abc123",
"title": "Industry News: Major Announcement",
"url": "https://example.com/article",
"relevanceScore": 85,
"triggerType": "market_shift"
},
"drafts": {
"twitter": "The market is shifting toward [topic]. This is exactly why we built [product]. Here's my take: [opinion based on stance]. What do you think?",
"linkedin": "I've been watching [topic] closely for the past few months...\n\n[Longer form content with paragraphs]\n\nWhat's your perspective on this shift?"
},
"quality": {
"score": 0.85,
"reasoning": "Strong connection to knowledge base and clear stance integration"
}
}

Requirements

  • Knowledge base must be configured
  • ANTHROPIC_API_KEY environment variable must be set

Analytics​

Track your Spring Intelligence performance.

Get Analytics​

GET /api/spring/analytics
GET /api/spring/analytics?days=30

Response

{
"period": {
"start": 1703000000000,
"end": 1706000000000,
"days": 30
},
"signals": {
"discovered": 150,
"relevant": 45,
"weak": 60,
"discarded": 45,
"used": 20
},
"drafts": {
"generated": 45,
"approved": 18,
"rejected": 12,
"edited": 15
},
"quality": {
"avgRelevanceScore": 72,
"avgEditDistance": 15,
"acceptanceRate": 40.0
},
"dailyBreakdown": [
{ "date": "2024-01-20", "signalsDiscovered": 5, "draftsGenerated": 2, "draftsApproved": 1 },
{ "date": "2024-01-19", "signalsDiscovered": 8, "draftsGenerated": 3, "draftsApproved": 2 }
]
}

Track Events​

Track draft approval/rejection for analytics.

POST /api/spring/analytics/track
Content-Type: application/json

{
"eventType": "draft_approved",
"signalId": "sig_abc123",
"editDistance": 12
}

Event Types

EventDescription
draft_generatedDraft was generated from signal
draft_approvedDraft was approved (include editDistance)
draft_rejectedDraft was rejected (include reason)
post_publishedContent was published (include platform)

Check Content Drift​

Detect if you're repeating topics too frequently.

GET /api/spring/analytics/drift?topic=serverless&days=7

Response

{
"hasDrift": true,
"similarTopics": [
"Serverless computing trends",
"Why serverless matters"
],
"lastMentioned": "2024-01-18T10:00:00Z"
}

Cron Worker​

Spring Intelligence includes a scheduled worker for automatic signal ingestion.

Deployment​

Deploy the signal ingestor as a separate Cloudflare Worker:

wrangler deploy -c wrangler.worker.toml

Schedule​

By default, the worker runs hourly to:

  1. Fetch sources due for checking
  2. Ingest content from RSS feeds and URLs
  3. Score relevance against your knowledge base
  4. Store high-relevance signals

SDK Examples​

TypeScript SDK​

import { Flow } from '@flowdev/sdk';

const flow = new Flow('flow_sk_live_...');

// Setup knowledge base
await flow.spring.updateKnowledge({
productName: 'My Product',
productFeatures: ['Feature 1', 'Feature 2'],
});

// Add signal source
await flow.spring.addSource({
type: 'rss',
label: 'Tech News',
config: { url: 'https://example.com/feed.xml' },
frequency: 'hourly',
});

// Get relevant signals
const { signals } = await flow.spring.getSignals({ status: 'relevant' });

// Generate draft from signal
const { drafts } = await flow.spring.generateDraft(signals[0].id);
console.log('Twitter:', drafts.twitter);
console.log('LinkedIn:', drafts.linkedin);

// Track approval
await flow.spring.trackEvent({
eventType: 'draft_approved',
signalId: signals[0].id,
editDistance: 10,
});

Python SDK​

from flow_sdk import Flow

flow = Flow('flow_sk_live_...')

# Setup knowledge
flow.spring.update_knowledge(
product_name='My Product',
product_features=['Feature 1', 'Feature 2']
)

# Get signals
signals = flow.spring.get_signals(status='relevant')

# Generate draft
drafts = flow.spring.generate_draft(signals[0]['id'])
print(f"Twitter: {drafts['twitter']}")

Best Practices​

Knowledge Base​

  1. Be specific about your target audience and ICP
  2. Include your tech stack for technical relevance matching
  3. Define clear hot takes for opinionated content generation

Signal Sources​

  1. Start with 3-5 high-quality sources rather than many mediocre ones
  2. Use semantic search for pain point discovery
  3. Monitor competitor changelogs for reactive content opportunities

Content Quality​

  1. Review and edit AI-generated drafts before publishing
  2. Track edit distance to improve generation over time
  3. Check for content drift to avoid repetitive topics

Performance Targets​

MetricTargetDescription
Acceptance Rate>30%% of drafts approved for publishing
Edit Distance<20%% of characters changed in approved drafts
Relevance Score>75 avgAverage score of processed signals

Error Codes​

StatusErrorDescription
400Knowledge base not configuredSetup knowledge before generating drafts
400URL already processedSignal deduplication in effect
400Invalid source typeMust be rss, url, or semantic_search
500AI generation not configuredANTHROPIC_API_KEY not set
500Failed to generate draftsLLM API error