The counsel loop
The reasoning core is one pure function with no SDK imports and no network of its own. Every dependency is injected, which is what makes the whole turn testable with fakes.
#Parsing intent
Before the model sees a token, the agent builds a deterministic frame for the turn — same text in, same frame out — because that frame is what the prompt and the recommendation extractor both ground against. The model gets to choose and explain; it never gets to invent the numbers.
export interface ParsedIntent {
goal: 'bridge' | 'swap' | 'yield' | 'unknown';
fromChain: ChainName | null;
toChain: ChainName | null; // null = "the best I can reach" — the agent picks
fromAsset: AssetSymbol | null;
toAsset: AssetSymbol | null;
amount: string | null; // decimal string in units of fromAsset
risk: RiskTolerance | null;
}Goal detection is intentionally ordered: yield intent dominates, so “move 500 USDC into the best ETH yield” is a yield goal, not a bridge — even though it contains the word “move.” That precedence is what makes the canonical demo sentence route correctly. Routes themselves come from a RouteProvider interface: a deterministic heuristic ships now, and real Bungee/Socket quoting slots in behind the same interface without touching the loop.
#The counsel turn
The whole algorithm is nine steps, and step 5 is the one that matters most:
export async function counselTurn(input, deps): Promise<AgentTurn> {
const turnId = deps.newTurnId();
const now = deps.now();
const memory = await deps.memory.loadStrategy(input.userId); // 1. hot cache; never blocks on 0G
const parsed = parseIntent(input.intent); // 2. structured frame
const routeCtx = deps.routes.context(parsed); // cross-chain options
const messages = buildPrompt(input.intent, memory, routeCtx); // 3. intent + memory + routes
const inference = await deps.compute.infer(messages); // 4. inference via 0G Compute (TEE)
const verification = await deps.compute.verify({ // 5. TEE attestation — REAL result only
provider: inference.provider, answer: inference.answer, chatId: inference.chatId,
});
const inferenceReceipt = { /* ... */ valid: verification.valid }; // never hardcoded true
const recommendation = extractRecommendation(inference.answer, routeCtx); // 6. grounded in routeCtx
const facts = deps.memory.consolidate({ /* ... */ }); // 7. distill durable facts (pure)
const memoryReceipt = await deps.memory.commit(input.userId, facts); // 8. cache now, 0G upload async
return { turnId, answer: inference.answer, recommendation, inferenceReceipt, memoryReceipt }; // 9.
}The verified flag is driven by the real verification result and nothing else. A turn whose TEE check fails is returned with the flag set to false. The answer is never thrown away, and an unverified call is never presented as verified — the UI gates the “Sworn” badge on exactly this flag.
#Grounded recommendations
The most dangerous thing an AI DeFi agent can do is hallucinate a number and render it as fact. Sworn makes that impossible: the model picks a direction and writes the rationale, but every figure shown is read back from the matching route candidate, never from the model’s text.
export function extractRecommendation(answer, routeCtx): Recommendation | null {
if (routeCtx.candidates.length === 0) return null;
const choice = parseModelChoice(answer); // reads the model's fenced json choice
if (choice === 'no-recommendation') return null; // honor a clarifying question
const candidate = choice ? matchCandidate(choice, routeCtx.candidates) : null;
const grounded = candidate ?? defaultCandidate(routeCtx); // best by risk tier
return candidateToRecommendation(grounded, choice); // numbers from candidate, prose from model
}The inference receipt proves the model ran in an enclave; the grounding discipline proves the numbers came from the route layer, not a hallucination. An attested model that is free to invent figures is still dangerous; a grounded number with no attestation is still unverifiable. Sworn ships both.
#Why it is testable
Because every dependency is a parameter — the compute client, the memory port, the route provider, the clock, the id source — a complete turn runs with a fake compute client, an in-memory store, and a frozen clock, asserting the receipts and the grounded recommendation without a single network call. Seven tests cover the agent package; three more in the API exercise the same loop against the real service wiring.