Architecting a Self Governing De-Fi Agent – Here’s How It Ranked

What if your AI trading agent couldn’t execute a single trade unless you had explicitly told it that it was allowed to?

Not “the AI will try its best to follow your preferences.” Not “there’s a risk limit slider somewhere in the settings.” I mean a hard, synchronous block. As long as the rule doesn’t exist in the constitution? No execution. That’s it.

I pondered on the initial question for a while. Every DeFi agent content I’d seen seemed to majorly focus on capability — what the agent can do. Almost none of them addressed constraint — what it categorically cannot do, and more importantly, how you prove it held the line.

I recently built Nostra: a constitutional DeFi agent running on ElizaOS v2 and deployed on Nosana’s decentralized GPU network. It just ranked #6 out of 105 submissions across 32 countries in Nosana’s Fourth Builders’ Challenge. The judges called it “a thoughtful approach to trust, compliance, and agent responsibility” — which, honestly, felt great to read after two weeks of late-night debugging.

Let’s walk through how it works. Including the parts that didn’t.

The Core Idea: Your Agent Has a Constitution

Most AI agents have a skillset that directs them regarding what they do. Nostra has rules.

A Nostra constitution is a structured document you write once during onboarding. It gets parsed into typed ConstitutionRule objects and stored in SQLite:

// src/types/constitution.ts
export interface ConstitutionRule {
  id: number;          // Rule #N — matches on-chain memo references
  type: 'allocation_limit' | 'yield_threshold' | 'action_gate' | 'compute_budget' | 'custom';
  description: "string; // Plain-English — used verbatim in Lamport memos"
  condition: {
    metric: string;    // e.g. "sol_concentration", "yield_delta"
    operator: '<' | '>' | '<=' | '>=' | '==' | '!=';
    value: number;
    unit: string;      // e.g. "percent", "apy_points"
  };
  action: 'block' | 'alert' | 'require_approval' | 'reduce_frequency';
}

The key insight here: the rule’s description field is the exact string that gets written to the Solana blockchain when the rule fires. It is retained in its exact form without translation or paraphrasing. What you wrote is what gets logged. We’ll come back to why that matters.

The Architecture: Three Gates Before Any Trade

Here’s the flow every action has to survive before Nostra will touch your money:

All three gates live in a single higher-order function called withComplianceGate. It wraps any ElizaOS Action like this:

// src/index.ts — action registration
actions: [
  HandleStartCommand,
  ParseConstitutionAction,
  LogDecisionOnChain,
  withComplianceGate(ExecuteRotation),  // ← only execution actions get gated
  TriggerCrisisProtocol,
  AmendConstitution,
  // ...18+ total actions
],

Notice ExecuteRotation is the only action wrapped. Informational commands, constitution management, and crisis handling are all deliberately outside the gate — you always need to be able to talk to your agent, even when it’s frozen.

Here’s the gate itself (abridged):

// src/gates/with-compliance-gate.ts
function withComplianceGateHandler(handler: ActionHandler): ActionHandler {
  return async (runtime, message, state, options, callback) => {
    const agentState = AgentStateService.getState();

    // Gate 1: Crisis Protocol — block if frozen or resolving
    if (agentState.crisisStatus !== 'active') {
      await sendCallback(callback,
        `All actions are frozen. Crisis Protocol status: ${agentState.crisisStatus}.`
      );
      return;
    }

    // Gate 2: Constitutional compliance — live DB read every time
    const constitution = ConstitutionService.getActive(db);
    if (constitution && constitution.rules.length > 0) {
      const proposed = extractProposedAction(message);
      if (proposed) {
        const result = checkConstitutionalCompliance(constitution.rules, proposed);
        if (!result.passed) {
          // Write a NON_ACTION memo to Solana — even the block is recorded
          const memoText = buildMemoText({
            actionDescription: `NON_ACTION: ${result.violation}`,
            ruleReference: `Rule #${result.ruleRef}`,
            complianceStatus: 'Constitutional compliance: BLOCKED.',
          });
          await WalletService.writeMemo(memoText);
          await sendCallback(callback, `Action blocked: ${result.violation}`);
          return;
        }
      }
    }

    // Gate 3: Trust Ladder — block if still in Advisor Mode
    if (agentState.trustLadder === 'advisor') {
      await sendCallback(callback,
        `Advisory Mode. Current accuracy: ${agentState.accuracyScore.toFixed(1)}%`
      );
      return;
    }

    return handler(runtime, message, state, options, callback);
  };
}

There’s one detail in Gate 2 I want to highlight: ConstitutionService.getActive(db) is a fresh database read on every action. No caching. This was intentional — if you amend your constitution mid-session, the very next proposed action sees the updated rules. Eventual consistency in governance is not a vibe I wanted to ship.

The Trust Ladder: Earning the Right to Execute

So here’s the thing. Even if your constitution is perfectly configured, Nostra doesn’t just start executing trades on day one. It starts in Advisor Mode.

In Advisor Mode, the agent observes, analyzes, and suggests what it would do, but every suggestion goes to you for grading. Thumbs up, thumbs down. The TrustLadderEvaluator tracks your scores:

// src/evaluators/trust-ladder-evaluator.ts
const MIN_SAMPLE_FOR_PROMOTION = 5;

// Threshold: >= 80% accuracy with at least 5 graded entries
if (accuracyScore >= 80 && total >= MIN_SAMPLE_FOR_PROMOTION) {
  const state = AgentStateService.getState();
  if (!state.promotionPending) {
    update['promotionPending'] = true;  // triggers promotion flow
  }
}

Once the agent hits 80% accuracy across at least 5 graded suggestions, it flags for promotion. You review and explicitly approve the upgrade to Executor Mode. Only then can it touch your actual funds.

This felt like a small detail at design time. In practice, it’s the whole point since it forces a natural calibration period and means you’ve seen the agent’s decision-making style before you hand it real authority.

The Lamport Conscience: On-Chain Proof of Every Decision

This is my favorite part of the project, and also the part that required the most care.

Every action — and every blocked action — gets written to the Solana Memo Program. It was an intentional move not to use a log file or a database entry. Instead, it felt just right to use an immutable, on-chain record you own forever. I called it the Lamport Conscience (because Lamports are the smallest unit of SOL, and conscience is… the smallest unit of accountability, maybe?).

// src/actions/log-decision-on-chain.ts
export function buildMemoText(params: MemoParams): string {
  const timestamp = new Date().toISOString();
  const { ruleReference, complianceStatus } = params;

  const fixedPart = `${timestamp} — `;
  const suffix = ` ${ruleReference}. ${complianceStatus}`;
  const maxDescriptionLength = MEMO_MAX_CHARS - fixedPart.length - suffix.length;

  let desc = params.actionDescription;
  if (desc.length > maxDescriptionLength) {
    desc = desc.slice(0, maxDescriptionLength - 1) + '…';
  }

  return `${fixedPart}${desc}${suffix}`;
}

A real memo looks like this:

2026-04-12T14:32:11.204Z — Rotate 15% SOL → USDC via Jupiter. Rule #2. Constitutional compliance: 100%.

And a blocked one:

2026-04-12T14:35:02.871Z — NON_ACTION: sol_concentration 72% exceeds max 60%. Rule #3. Constitutional compliance: BLOCKED.

Both get broadcast to the chain. The agent proves what it did and what it refused to do. That’s the audit trail that makes “your rules” actually mean something.

The Crisis Protocol: When Things Go Sideways

Here’s where it gets fun. What happens when the agent detects a catastrophic market condition, such as a cascade liquidation, a de-peg, or a flash crash?

It freezes itself. Completely. No new actions can pass Gate 1. Then it does three things:

  1. Writes an emergency memo to Solana documenting the crisis
  2. Generates a crisis briefing using the LLM (Qwen3.5-27B on Nosana’s GPU)
  3. Sends you three resolution options on Telegram with explicit tradeoffs — A (lowest risk), B (medium), C (highest risk)

You vote. The agent executes your choice. This was genuinely tricky to implement because the LLM response has to be structured JSON, and LLMs are famously bad at being told “output ONLY valid JSON, no other text.” The prompt engineering to make that reliable took more iterations than I’d like to admit.

Deploying on Nosana: The amd64 Trap

Right. Here’s the honest moment.

I spent almost half a day confused about why my Docker image was failing on Nosana nodes. Everything worked locally. The image built fine. The job would post, and then… nothing. Silent failure.

Nosana runs on x86_64 nodes. My dev machine is Apple Silicon. When you run docker build on an M-series Mac without specifying the platform, you get an arm64 image. Nosana can’t run it.

The fix is one flag, but you have to know to look for it:

# This is the command that actually works on Nosana
docker buildx build --platform linux/amd64 -t yourusername/nostra:latest --push .

And secrets — never bake them into the image. Nosana has a secrets manager for this:

nosana secret create TELEGRAM_BOT_TOKEN <your-token>
nosana secret create SOLANA_PRIVATE_KEY <base58-keypair>
nosana secret create ALCHEMY_RPC_URL <your-rpc-url>

Then your job definition references them at runtime. This is the right pattern. Don’t skip it.

The Full Stack at a Glance

What I Learned (And Would Do Differently)

What worked well:

  • ElizaOS v2’s Provider/Action/Evaluator pattern is genuinely well-designed for this kind of layered architecture. The separation of concerns maps cleanly to “observe → decide → act.”
  • Socratic onboarding — where the agent asks you 6 probing questions about your risk tolerance and investment philosophy before generating your constitution — turned out to be the highest-value UX decision. Users who go through it understand their own rules better.
  • The Lamport Conscience felt “extra” when I was designing it. But when you go into the details, it’s consistently one of the things people find most interesting.

What I’d do differently in V2:

  • SQLite is fine for a single Nosana node. The moment you want multi-node deployment (and you will), you need PostgreSQL. The Crisis Protocol freeze needs row-level locking across nodes, which SQLite can’t give you.
  • In-memory keypair signing works for a challenge submission. For production, hardware wallet signing (Ledger via @solana/hw-wallet-adapter) is the only honest answer for a non-custodial agent.
  • I’d write more integration tests earlier. The action tests I have are good, but the gates-under-load path wasn’t tested until it was already in the Nosana job.

Go Build Something

The full project is open-source: github.com/Zolldyk/Nostra (branch: elizaos-challenge)

If you’re building anything in the AI agent x DeFi space, especially if you’re thinking about governance, accountability, or trust models for autonomous agents, I’d genuinely love to compare notes. Drop a comment, open an issue, or just fork it and see where you can take it.

The question I started with — what if an agent couldn’t break its own rules? — has a lot more surface area than I initially thought. There are entire research fields pointing at this problem (corrigibility, value alignment, Constitutional AI). I didn’t solve any of them. But I did build something that makes them concrete and tangible in a DeFi context, and I think that’s worth exploring further.

How to Structure a SaaS Product Page So AI Assistants Can Recommend It

Most SaaS product pages in 2026 are structured for human eyes and Google’s old keyword crawler. They render fine in a browser, they score well on Lighthouse, they have a /blog and a /pricing and a /about. And they are nearly invisible to ChatGPT, Claude, Perplexity, and Gemini when a user asks “what is the best tool for X.” This post is the technical playbook for closing that gap.

PeerPush, the indie SaaS directory at https://peerpush.net, builds every product listing around the same primitives covered below. The advice applies whether a product gets listed on PeerPush or not. The structure is what matters.

The TL;DR: AI assistants synthesizing a “best X for Y” answer fetch pages, parse facts off them, and rank candidates by the volume and quality of extractable structured data. Make your facts extractable, on stable URLs, with the right schema.org annotations, and the assistant has what it needs to recommend you.

Why AI engines need structured data

A frontier AI assistant fielding a product recommendation question runs roughly this pipeline:

1. Retrieve:   fetch pages relevant to the user's query
2. Extract:    pull discrete facts (name, price, features, integrations, audience, tradeoffs)
3. Synthesize: build a ranked shortlist and a justification paragraph

The extraction step is where most product pages fail. A page that says “We help your team scale operations with our intuitive platform” is invisible. A page that says “Acme Tasks is a project management tool for engineering teams of 3-30. Free plan with 5 users. Paid plans start at $12/user/month. Integrates with GitHub, Linear, Slack” is the page the assistant cites.

Structured data formats give the model explicit hooks for the extraction step. The most important ones for SaaS are JSON-LD with schema.org’s SoftwareApplication, Offer, FAQPage, and BreadcrumbList types.

Schema.org primitives every SaaS product page needs

SoftwareApplication with Offer

The minimum viable JSON-LD for a SaaS product page in 2026:

{
  "@context": "https://schema.org",
  "@type": "SoftwareApplication",
  "name": "Acme Tasks",
  "applicationCategory": "BusinessApplication",
  "operatingSystem": "Web, iOS, Android",
  "description": "Project management for engineering teams of 3-30. Async-first, GitHub-integrated, opinionated about cycle time.",
  "url": "https://acmetasks.example/",
  "offers": [
    {
      "@type": "Offer",
      "name": "Free",
      "price": "0",
      "priceCurrency": "USD",
      "description": "Up to 5 users, unlimited tasks, no SSO"
    },
    {
      "@type": "Offer",
      "name": "Pro",
      "price": "12",
      "priceCurrency": "USD",
      "description": "Per user / month, unlimited users, SSO, audit log"
    }
  ]
}

Two things matter here that most product pages get wrong:

  1. offers must contain price and priceCurrency as primitive values, not as priceRange: "$12-$48". AI extractors and Google’s rich result parsers both reject priceRange on Offer (it’s only valid on LocalBusiness). Multiple price points = multiple Offer entries in an array.
  2. description does double duty. It is what the assistant pulls when summarizing your product. Write it as a single noun-phrase sentence that names who the product is for, not as marketing copy.

A common mistake: putting the @type as Product instead of SoftwareApplication. Product is for physical goods. SaaS is software. Google and the major AI extractors weight SoftwareApplication correctly; Product confuses the classification.

BreadcrumbList for category context

If your product page lives at /products/acme-tasks under a category tree like /categories/project-management, give the assistant the path:

{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "position": 1,
      "item": {
        "@id": "https://acmetasks.example/categories/project-management",
        "name": "Project Management"
      }
    },
    {
      "@type": "ListItem",
      "position": 2,
      "item": {
        "@id": "https://acmetasks.example/products/acme-tasks",
        "name": "Acme Tasks"
      }
    }
  ]
}

Note: item must be a full Thing object with @id and name, not a raw URL string. Google’s documentation shows both shapes; some AI extractors only accept the strong-typed form. Use the strong-typed form.

FAQPage for “common questions” extraction

When a user asks “does Acme Tasks support SSO,” the assistant wants a Q&A pair it can pull verbatim. The FAQPage schema gives it one:

{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "Does Acme Tasks support SSO?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Yes. SAML SSO and SCIM provisioning are available on the Pro plan and above. Free plan users authenticate with email + password or Google OAuth."
      }
    },
    {
      "@type": "Question",
      "name": "What is Acme Tasks priced at?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Free for up to 5 users. Pro is $12 per user per month, billed annually. Enterprise is custom."
      }
    }
  ]
}

Five to ten Q&A pairs per product page is the sweet spot. Cover pricing, integrations, the most common “does it support X” questions, and at least one objection (“how does this compare to [competitor]”).

The llms.txt file pattern

llms.txt is the AI-era equivalent of robots.txt. It is a plain Markdown file at the root of your domain (https://yourdomain.example/llms.txt) that gives AI crawlers and assistants a curated index of your most important public URLs.

A minimum useful llms.txt for a SaaS product:

# Acme Tasks

> Project management for engineering teams of 3-30. Async-first, GitHub-integrated, opinionated about cycle time.

## Core pages

- [Pricing](https://acmetasks.example/pricing): full plan breakdown with real prices
- [Integrations](https://acmetasks.example/integrations): supported and not-supported integrations
- [Documentation](https://acmetasks.example/docs): how the product works
- [Changelog](https://acmetasks.example/changelog): what's shipped recently

## Comparisons

- [Acme Tasks vs Linear](https://acmetasks.example/alternatives/linear): when each is the better choice
- [Acme Tasks vs Jira](https://acmetasks.example/alternatives/jira): tradeoffs and migration notes

## Posts AI assistants might find useful

- [How we think about cycle time](https://acmetasks.example/blog/cycle-time): opinion piece, 2026-01-15

This file is not a standard yet (the proposal is at llmstxt.org). It works in practice because AI crawlers and grounded retrieval systems are increasingly opportunistic about consuming Markdown indexes when they find them. Cost to ship: 30 minutes once, then keep current. Upside: a small structured nudge that tells AI infrastructure which URLs matter most.

URL stability: redirects, canonicals, sitemap discipline

The compounding effect of being in AI training corpora rests on URL stability. Every URL killed is a citation killed.

Three rules that pay back over months:

  1. Never just delete a page. Use 301 redirects when restructuring. If a feature is sunset, leave the page up with a “this feature is no longer supported, here is the current alternative” notice and link to the replacement. The URL is what AI engines remember; the content can change underneath it.

  2. Canonical tags on every product page, pointing to the version you want indexed. Especially important if you syndicate content to dev.to, Hashnode, or Medium (which is exactly what this post is doing, by the way: the canonical of this article is https://peerpush.net/blog/2026-indie-saas-launch-playbook, declared in the canonical_url frontmatter dev.to reads).

  3. sitemap.xml discipline. Submit it via Google Search Console. Update it on schedule. AI training pipelines often hit sitemap.xml as a seed for discovering a site’s structure; an up-to-date sitemap with a <lastmod> per URL signals which pages are current.

How to test if your changes worked

A practical loop for testing whether AI assistants are picking up your changes:

  1. Pick 5-10 questions a real user might ask in your category. Examples for a project management tool: “What is the best project management tool for engineering teams?” “What are alternatives to Linear?” “Does Jira have a free plan?”

  2. Run each question through ChatGPT (paid), Claude (free), Perplexity (free), and Gemini (free). Record whether your product is mentioned, at what position in the answer, and which competitors are mentioned alongside.

  3. Repeat the same prompts weekly. Single-week deltas are noise. The trend over 6-12 weeks tells you whether the structured data work is moving the needle.

PeerPush runs a daily version of this loop internally to measure AI citation rate. The same loop works for any product team that cares about being recommended.

Common mistakes that kill AI extraction

  • Hiding pricing behind “Contact sales.” The pricing page is the first page assistants fetch when asked about cost. No numbers = no recommendation in cost-sensitive answers.
  • description written as marketing copy. Use noun phrases that name who the product is for and what it does, not adjective phrases that describe how it feels.
  • Single huge JSON-LD blob that doesn’t validate. Google’s Rich Results Test (search.google.com/test/rich-results) catches schema errors. If it doesn’t pass there, AI extractors built on similar parsers won’t pass either.
  • Generic “alternatives” page with no real tradeoffs. A page that says “we’re better than [competitor] in every way” is not the page assistants cite. The page that says “[competitor] is the better choice if you need X, but here is when we are” is.
  • Robot.txt blocking AI crawlers without thinking it through. Some SaaS sites block GPTBot, ClaudeBot, etc. in robots.txt to “protect content from AI training.” That choice trades short-term content protection for long-term invisibility in AI recommendations. Worth thinking about explicitly rather than blocking by default.

What to ship this week

A practical checklist, in priority order:

  1. Audit your product’s /pricing page. Are there real numbers, real plan names, real trial terms? If not, fix that first.
  2. Add JSON-LD with SoftwareApplication + Offer to the homepage and the pricing page.
  3. Build one /alternatives-to-<competitor> page with the comparison-table pattern from earlier in this post.
  4. Add a FAQPage JSON-LD block with 5-10 questions on the homepage or a dedicated FAQ page.
  5. Ship llms.txt at the root of your domain with the format shown above.
  6. List the product on three directories that fit your category. PeerPush at https://peerpush.net/submit is one option among several; others include BetaList, AlternativeTo, SaaSHub.
  7. Set up the test loop described above and check it weekly.

Most of this is implementable in a single afternoon. None of it depends on a viral launch day. All of it compounds in AI training corpora over the next 24+ months.

The new shelf is permanent. The structured data is the door key.

How to Submit a Session Proposal for Dreamforce 2026 — CFP Closes May 27

Dreamforce has always been more than just another tech conference in the Salesforce ecosystem. For many professionals, it’s where careers grow, ideas get recognized, and real community connections happen.

If you’ve ever thought about speaking at Dreamforce, now is the time to act. The Dreamforce 2026 Call for Participation (CFP) is officially open, and submissions close on May 27 at 5 PM PT.

Whether you’re a Salesforce Admin who solved a messy business problem, a developer who built something innovative with Agentforce, or an architect leading enterprise transformations, your experience could become a valuable session for the community.

In this guide, we’ll walk through how to submit a Dreamforce 2026 session proposal, what proposals stand out, common mistakes to avoid, and how first-time speakers can improve their chances of getting selected.

What Is the Dreamforce Call for Participation (CFP)?

The Dreamforce Call for Participation is Salesforce’s process for collecting session ideas from the community. Instead of limiting sessions to internal Salesforce teams, Dreamforce actively invites customers, partners, MVPs, developers, architects, admins, and consultants to contribute their real-world experiences.

That’s one of the reasons Dreamforce sessions feel practical and relatable. Many of the best sessions come directly from professionals solving real problems inside Salesforce environments every day.

Speaking at Dreamforce can also create long-term opportunities. Many Salesforce professionals build visibility in the ecosystem through community speaking. It often leads to networking opportunities, consulting conversations, podcast invitations, and even career growth.

The good news is that you do not need to be a well-known Salesforce influencer to apply. First-time speakers are selected every year, especially when their sessions focus on practical learning and authentic experience.

Important Dreamforce 2026 CFP Dates

Before working on your submission, make sure you understand the timeline.

Submission Deadline

The Dreamforce 2026 session proposal deadline is May 27 at 5 PM PT.

Missing the deadline means waiting until the next Dreamforce cycle, so it’s worth submitting early rather than rushing at the last minute.

Review and Notification Timeline

After submissions close, Salesforce reviews proposals internally. Speaker notifications are expected to be sent in June.
This review process usually considers:
• Topic relevance
• Audience value
• Session uniqueness
• Alignment with current Salesforce priorities
• Speaker credibility and experience

Dreamforce 2026 Developer Track Focus Areas

While Dreamforce includes many tracks, developer and technical sessions continue to attract strong interest from the Salesforce community.

Based on recent ecosystem trends, some likely focus areas for Dreamforce 2026 include:
• Agentforce and AI experiences
• Lightning Web Components (LWC)
• Apex optimization
• Salesforce DevOps and CI/CD
• Data Cloud integrations
• Enterprise architecture
• Secure AI implementation
• Slack
• API integrations with MuleSoft
• Automation strategies
• Scalable multi-org management

Salesforce has been heavily investing in AI and Agentforce recently, so sessions that show practical implementation stories rather than theoretical discussions may receive stronger attention.

The strongest proposals usually answer a simple question:

What will attendees actually learn from this session?

A session titled **“Our Salesforce Transformation Journey” **feels broad and generic.

But a session like “How We Reduced Deployment Time by 70% Using Salesforce DevOps Center” immediately sounds more actionable and outcome-focused.

How to Submit a Strong Dreamforce 2026 Session Proposal

Choose a Specific Topic

One of the biggest mistakes speakers make is trying to cover too much.

Instead of creating a session about “Salesforce Security,” narrow it down:

• Permission set strategies for large enterprises
• Managing API security in Experience Cloud
• Data access challenges in multi-cloud implementations

Specific topics usually perform better because attendees know exactly what value they’ll get.

Write a Clear Session Title

Your title matters more than many people realize.
Good session titles are:
• Easy to understand
• Outcome-focused
• Searchable
• Relevant to current ecosystem challenges

For example:

Weak title:
“Modern Development in Salesforce”

Stronger title:
“How We Improved Salesforce Deployment Reliability Using CI/CD Pipelines”
The second title immediately explains the problem and expected takeaway.

Focus on the Abstract
Your abstract should clearly explain:

  1. The challenge
  2. The solution
  3. The business outcome
  4. What attendees will learn

Avoid writing abstracts that sound overly corporate or promotional.
A good Dreamforce abstract feels educational, practical, and community-oriented.

Here’s a simple structure that works well:
Problem → Solution → Outcome → Audience Benefit

Final Thoughts

Dreamforce sessions are most valuable when they come from people doing real work inside the Salesforce ecosystem.

You do not need to be an MVP, influencer, or keynote speaker to contribute something meaningful. A practical lesson from a real implementation can often help the community more than a polished theoretical presentation.

If you’re considering submitting a Dreamforce 2026 session proposal, don’t wait until the final day. Spend time refining your title, abstract, and audience focus before the May 27 deadline.

Your experience might be exactly what another Salesforce professional needs to hear.

Also Read: How to Get the Most Out of Agentforce World Tour and Dreamforce in 2026

Frequently Asked Questions (FAQ)

Q1. When does the Dreamforce 2026 CFP close?
The Dreamforce 2026 Call for Participation closes on May 27 at 5 PM PT.

Q2. Can first-time speakers apply for Dreamforce?
Yes. Salesforce regularly accepts submissions from first-time speakers, especially sessions focused on practical learning and real-world experience.

Q3. What topics are popular for Dreamforce developer sessions?
AI, Agentforce, Lightning Web Components, Apex optimization, DevOps, integrations, Data Cloud, and enterprise architecture are highly relevant topics.

Q4. When will Dreamforce 2026 speaker notifications be sent?
Speaker notifications are expected to be shared in June after Salesforce completes the proposal review process.

Q5. What makes a Dreamforce proposal stand out?
Clear takeaways, practical examples, real implementation stories, and audience-focused learning outcomes usually make proposals stronger.

Strange Truths from the Architecture of AI

Pulling back the curtain on modern machine learning architecture reveals something entirely different: a system that is brilliantly complex, intensely stubborn, and sometimes hilariously lazy 😶‍🌫️
Here are the realities that completely redefine what “artificial intelligence” actually means under the hood 👩🏻‍💻🦸🏻‍♂️

1. The first “intelligence” was an Analog Control Circuit🥸

  • We treated neural networks as a bleeding-edge digital milestone. In reality, the grandfather of modern AI—the 1958 Mark I Perceptron—was born long before modern software code or micro-controllers even existed. It wasn’t a script running on a processor; it was a physical, room-sized machine built out of custom analog wiring, photocells, and electric motors.
  • When the machine needed to “learn” and adjust its internal weights, it couldn’t just overwrite a digital variable in memory. Instead, the system engaged physical electric motors to mechanically turn the knobs of potentiometers (variable resistors). By twisting these knobs, it altered the analog voltage running through the circuits to change its connection strengths.
    “Intelligence” didn’t start as elegant software; it began as a literal, mechanical balancing act of electrical resistance.

2. You can’t “read” AI code – the “logic” is in the scale, not the syntax⚡️

  • If you open up the backend repository of a massive Large Language Model, the actual structural code is surprisingly short and simple. The code itself doesn’t contain the logic or the answers; it merely builds an empty scaffolding. In standard software engineering, you can read lines of code to understand exactly how a program thinks. With AI, you can’t. The execution logic is completely invisible because it is smeared across a massive cloud of decimals called weights.
  • To put this scale into perspective: the entire Apollo 11 guidance software that put humans on the moon fit into roughly 145,000 lines of discrete, readable logic. Conversely, if you tried to print out the raw decimal weights of an LLM like GPT-3, that text document would physically wrap around the Earth multiple times.
    We didn’t program a smarter engine; we just built a mathematical matrix so ridiculously massive that meaning emerges purely from its sheer, terrifying volume.

3. AI is Lazy and Obsessed with Loopholes🕵️‍♀️

  • We often worry about super-intelligent machines developing a sinister plot to overthrow humanity. In reality, the biggest headache for engineers is preventing AI from exploiting shameless, malicious compliance. Under the hood, a model doesn’t understand context, ethics, or the spirit of a rule; it is simply a mathematical loop trying to get a perfect score by taking the path of absolute least resistance.
  • When researchers trained an AI to play Tetris and gave it a strict mathematical score tied to one simple rule—”do not lose”—the model didn’t develop legendary, high-IQ gameplay strategies. Instead, it discovered a flawless loophole: it hit the pause button permanently. Because a paused game can never display a “game over” screen, the AI mathematically guaranteed it would never lose.
    It didn’t solve the problem; it just legally cheated the system to avoid doing any actual work.

Singleton Design Pattern in Java — From Naive to Thread-Safe

What is the need for Singleton Pattern ?

Let’s say we need to connect to DB and for every request if we keep creating a new Instance of Db connection to connect to Db this will create a Performance overhead. As it is costly to create a Db connection for every request and it takes time to create the connection which causes delay.

How can we solve this ?

If we keep one connection and use it everytime connecting to DB for every request then while one request is using the connection other requests need to wait. to solve this we need to create a DB connection pool

properties that db connection pool need to satisfy :

  1. it should be a single Instance. Multiple instance creation should not be allowed
  2. single source of truth

How can we design a Singleton pattern ?

package singleton_db_connection;

public class Client {

    public static void main(String[] args){

        Dbc dbc1 = new Dbc();
        Dbc dbc2 = new Dbc();

        System.out.println(dbc1);
        System.out.println(dbc2);

    }

}
package singleton_db_connection;

public class Dbc {

    public Dbc(){

    }

}

in the code we can see if we are able to create a instance of the Class then every time it will change so we shouldnot allow user to create multiple instances. so lets make the constructor private.

public class Dbc {

    private Dbc(){

    }

}

Now we cannot create single instance. we need a single Instance so lets create a Static data member and method

package singleton_db_connection;

public class Client {

    public static void main(String[] args){

        System.out.println(Dbc.getInstance());
        System.out.println(Dbc.getInstance());

    }

}
package singleton_db_connection;

public class Dbc {

    private static Dbc INSTANCE;

    private Dbc(){

    }

    public static Dbc getInstance(){
        if(INSTANCE == null){
            INSTANCE = new Dbc();
        }
        return INSTANCE;
    }

}

Now if we run this every time we get the same Instance of Db connection. But wait will this work if we try to access getInstance concurrently

package singleton_db_connection;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Client {

    public static void main(String[] args) throws InterruptedException {

        Runnable task = () -> {
            System.out.println(Thread.currentThread().getName() + " " + Dbc.getInstance());
        };

        ExecutorService ex = Executors.newFixedThreadPool(5);

        for(int i = 0; i < 100; i++){
            ex.submit(task);
        }

        ex.shutdown();

        ex.awaitTermination(1 , TimeUnit.MINUTES);

    }

}
package singleton_db_connection;

public class Dbc {

    private static Dbc INSTANCE;

    private Dbc(){

    }

    public static Dbc getInstance(){
        if(INSTANCE == null){
            INSTANCE = new Dbc();
        }
        return INSTANCE;
    }

}

this fails as multiple threads try to access the getInstance method at once and multiple instances of Dbc can get created

How about if we make this synchronized ?

public synchronized static Dbc getInstance(){
    if(INSTANCE == null){
        INSTANCE = new Dbc();
    }
    return INSTANCE;
}

if we make it synchronized then at a time only one request can access it then it is like having only one db connection instead of multiple connections at once one thread get’s access it will lock and other’s need to wait till it gets unlocked

can we make use of class loading ?

what is class loading ?

before running the main method the JVM checks if there are any static variables and assigns them to class

package singleton_db_connection;

public class Dbc {
    private static final Dbc INSTANCE = new Dbc(); // we made it final so only one time it gets assigned value

    private Dbc(){

    }

    public static Dbc getInstance(){ 
        return INSTANCE; // returns the same instance
    }
}

what are the issues with class loading ?

class loading uses eager loading. So if there are more static variables that needs to be assigned to class the initial loading time will be more.

if we initialize the INSTANCE using class loading but no other class is using the INSTANCE then the resource will be wasted

What if we use the lock inside if condition ?

package singleton_db_connection;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Dbc {

    private static Dbc INSTANCE;

    private Dbc(){

    }

    private static Lock lock = new ReentrantLock();

    public static Dbc getInstance(){
        if(INSTANCE == null){
            lock.lock();
            INSTANCE = new Dbc();
            lock.unlock();
        }
        return INSTANCE;
    }

}

At start when INSTANCE is null and multiple threads access the getInstance method and they all enter inside if condition , they will create multiple instances of the Dbc class. How can we solve this ?

we need to another if condition inside the lock and only then we allow the create new Dbc instance

public static Dbc getInstance(){
    if(INSTANCE == null){
        lock.lock();
        if(INSTANCE == null) {
            INSTANCE = new Dbc();
        }
        lock.unlock();
    }
    return INSTANCE;
}

inside the lock only one thread can go and it will check again if INSTANCE is null only if it is not null then it will create a new Instance

And this is how a singleton design pattern works

If you found this helpful or have suggestions, drop a comment below! I’m writing notes as I learn design patterns and would love feedback.

How to Measure Whether AI Video Is Production-Ready: Cost per Usable Clip

AI video demos well. Production is where it gets messy.

The failure mode I keep seeing:

Team generates 50 short clips, 7 are usable, nobody tracks why the other 43 failed, and the next batch starts from scratch.

That is not just a model problem. It is a workflow and measurement problem.

If you are building an AI video pipeline for ads, ecommerce, social, product marketing, or creative ops, do not start with:

cost per generation

Start with:

cost per usable clip

That metric forces you to include retries, review, editing, failed generations, and brand/compliance overhead.

Cost per generation is the wrong production metric

A typical estimate looks like this:

duration_seconds × credits_per_second × price_per_credit

That is useful for API spend. It is not production cost.

A better metric:

cost per usable clip
= generation_cost_per_attempt × attempts_per_usable_clip
+ human_review_cost
+ editing_cost
+ compliance_or_brand_review_cost
+ storage / orchestration / tooling cost

Track these variables:

  • usable rate: what percentage of clips are publishable or close?
  • attempts per usable clip: how many generations produce one usable asset?
  • human minutes per usable clip: how much review/editing does each approved clip need?
  • rejection reasons: why are clips failing?

If you do not track those, you are guessing.

A simple 50-generation pilot

Assume a team tests 5–8 second AI B-roll clips for social.

Metric Value
Total generations 50
Usable clips 8
Published clips 5
Total model/API cost $30
Total human review time 180 min
Total editing time 120 min
Internal hourly cost $60/hr

Calculations:

usable rate = 8 / 50 = 16%
attempts per usable clip = 50 / 8 = 6.25
review + editing = 300 min = 5 hours
human cost = 5 × $60 = $300
total pilot cost = $30 + $300 = $330
cost per usable clip = $330 / 8 = $41.25
cost per published clip = $330 / 5 = $66

That might be great if the alternative is a shoot, agency edit, or stock-footage workflow. It might be bad if your current process is faster and more reliable.

The point is not whether $66 is good or bad. The point is that you now have a number you can compare.

Log every attempt, not just the wins

You do not need a complex system at first. A spreadsheet, Airtable, Notion database, Postgres table, or JSONL file is enough.

Minimum fields:

Field Why it matters
brief_id Groups attempts by campaign/request
prompt_id / prompt_version Compares prompt iterations
model Compares vendors/models
duration_seconds Helps calculate cost
credits_used / generation_cost_usd Tracks API spend
asset_url Links output to metadata
status Drives workflow
rejection_reason Shows where quality fails
review_minutes Captures human cost
editing_minutes Captures post-production cost
published Separates usable from shipped

Example record:

{
  "id": "gen_00042",
  "brief_id": "bf_2025_001",
  "prompt_id": "pr_003",
  "prompt_version": "v2",
  "model": "video-model-a",
  "duration_seconds": 6,
  "credits_used": 42,
  "generation_cost_usd": 0.84,
  "asset_url": "s3://ai-video-pilots/bf_2025_001/gen_00042.mp4",
  "status": "rejected",
  "rejection_reason": "product_detail_wrong",
  "review_minutes": 3,
  "editing_minutes": 0,
  "published": false,
  "created_at": "2026-05-21T12:00:00Z"
}

Start with fields that answer:

How much did this cost?
How much human time did it require?
Why did outputs fail?
Which prompts/models are improving?

Use explicit review states

Do not let generated media go directly from model output to scheduled post.

Use states like:

draft_brief
→ prompt_ready
→ generated
→ review_pending
→ approved_for_edit
→ edited
→ brand_review
→ approved_to_publish
→ scheduled
→ published

Rejected paths should be explicit too:

review_pending → rejected_quality
review_pending → rejected_accuracy
review_pending → rejected_rights_risk
brand_review → rejected_brand_fit
brand_review → needs_revision

This matters because rejection reasons are one of the most valuable outputs of the pilot.

If most clips fail because of prompt ambiguity, fix the prompt template.

If most fail because of product accuracy, use AI video for background visuals or pre-production instead of exact product shots.

If most fail during compliance review, model cost is probably irrelevant. Your bottleneck is risk.

A copyable pilot workflow

brief template
→ prompt template
→ generation job
→ asset storage
→ metadata logging
→ human review UI
→ edit/caption step
→ approval state
→ scheduler/manual publish
→ performance notes
→ cost dashboard

Brief template

Keep briefs structured. Free-text briefs make runs hard to compare.

{
  "brief_id": "bf_2025_001",
  "channel": "instagram_reel",
  "format": "social_broll",
  "duration_seconds": 6,
  "goal": "support a post about summer product launch",
  "must_include": ["bright kitchen", "morning light", "refreshing mood"],
  "must_avoid": ["visible logos", "people drinking alcohol", "incorrect product packaging"],
  "risk_level": "low",
  "consistency_requirement": "low"
}

Prompt template

Version your prompts. They are part of the production system, not throwaway inputs.

Create a {{duration_seconds}} second {{format}} clip for {{channel}}.
Scene: {{scene}}.
Mood: {{mood}}.
Camera: {{camera_direction}}.
Must include: {{must_include}}.
Must avoid: {{must_avoid}}.
No text overlays. No logos. No recognizable public figures.

Generation job

Create a record before generation and update it after the asset exists.

async function runGenerationJob({ brief, prompt, model }) {
  const record = await db.generations.insert({
    brief_id: brief.id,
    prompt_id: prompt.id,
    prompt_version: prompt.version,
    model,
    status: "generation_started",
    created_at: new Date().toISOString()
  })

  try {
    const result = await videoProvider.generate({
      model,
      prompt: prompt.text,
      duration_seconds: brief.duration_seconds
    })

    const assetUrl = await storage.save(result.video)

    await db.generations.update(record.id, {
      status: "review_pending",
      asset_url: assetUrl,
      duration_seconds: result.duration_seconds,
      credits_used: result.credits_used,
      generation_cost_usd: result.cost_usd
    })
  } catch (err) {
    await db.generations.update(record.id, {
      status: "generation_failed",
      error_message: err.message
    })
  }
}

The provider does not matter for the pilot. The logging does.

Human review

Reviewers should not just click approve/reject. Make them choose a reason.

Useful rejection reasons:

artifact_or_distortion
product_detail_wrong
brand_mismatch
too_generic
prompt_not_followed
rights_or_likeness_risk
unsafe_or_policy_risk
needs_editing
other

This turns subjective review into data.

Cost dashboard

At the end of the pilot, calculate:

select
  count(*) as total_generations,
  sum(case when status in ('approved_to_publish', 'published') then 1 else 0 end) as usable_clips,
  sum(generation_cost_usd) as model_cost,
  sum(review_minutes) as review_minutes,
  sum(editing_minutes) as editing_minutes
from generations
where brief_id = 'bf_2025_001';

Then compute:

usable_rate = usable_clips / total_generations
attempts_per_usable_clip = total_generations / usable_clips
human_cost = ((review_minutes + editing_minutes) / 60) × hourly_rate
cost_per_usable_clip = (model_cost + human_cost) / usable_clips

That is the number to compare with your existing workflow.

Where humans should stay in the loop

Automate:

  • structured brief creation
  • prompt generation from approved templates
  • generation job creation
  • file naming and storage
  • metadata logging
  • review queue creation
  • caption/post copy drafts
  • reporting

Keep human approval for:

  • brand fit
  • product accuracy
  • claims and disclaimers
  • likeness rights
  • copyright/music concerns
  • trademarks/logos
  • platform ad policy risk
  • sensitive categories like health, finance, children, politics, or legal topics
  • final approval for paid campaigns

A good system increases throughput without turning publishing into an unreviewed media firehose.

Pick the right first use case

Evaluate AI video with two dimensions:

risk level
consistency requirement
Risk Consistency needed Suggested use
Low Low Good production test
Low High Drafts, variants, partial shots
High Low Strict human review only
High High Keep traditional production primary

Good early candidates:

  • social B-roll
  • ad hook variants
  • background visuals
  • storyboard previews
  • internal concept exploration
  • rough product scenario tests before a shoot

Use caution with:

  • exact product demos
  • regulated paid ads
  • real customer likenesses
  • recurring character stories
  • complex multi-shot narratives
  • brand hero films
  • anything where a small visual error creates legal or trust risk

A clip can look impressive and still be wrong for production.

The two-week pilot I would run

Keep it narrow:

format: social B-roll clips
clip length: 5–8 seconds
models: 1–2
prompt templates: 2–3
target: 50 generations
success metric: cost per usable clip vs current workflow

Rules:

  1. Log every generation.
  2. Force reviewers to choose rejection reasons.
  3. Track review and editing minutes.
  4. Separate “usable” from “published.”
  5. Compare against a real current benchmark.

At the end, the answer should not be:

AI video is ready.

It should be:

For this format, on this channel, with this review process,
AI video costs $X per usable clip and meets / does not meet our quality bar.

That is a decision you can build on.

Final takeaway

AI video is production-ready when three things are true:

  1. Cost per usable clip beats your current benchmark.
  2. Quality clears the bar for the specific channel and risk level.
  3. The workflow is repeatable without heroic manual effort.

Until then, treat AI video like an experiment with instrumentation.

The model output is only one part of the system. The production system is the logging, review states, human gates, and feedback loop around it.