Skip to content

docs: surface tutorial 31 (plugins) and fix stale source links#3

Closed
fede-kamel wants to merge 1 commit into
mainfrom
feat/initial-locus-public-release
Closed

docs: surface tutorial 31 (plugins) and fix stale source links#3
fede-kamel wants to merge 1 commit into
mainfrom
feat/initial-locus-public-release

Conversation

@fede-kamel
Copy link
Copy Markdown
Contributor

Small follow-up to PR #2 (just merged).

What's wrong

Two things the audit caught after PR #2 was queued for merge:

  1. Tutorial 31 (plugins) was orphanedexamples/tutorial_31_plugins.py exists in the tree but had zero references anywhere in the docs site. New users who wanted to learn the Plugin pattern had no entry point.
  2. Two stale source-path links in concept pages pointed at paths that no longer exist:
    • src/locus/integrations/mcp/ — the package was flattened to src/locus/integrations/fastmcp.py. Affected docs/concepts/mcp.md and the introspect table on docs/index.md.
    • src/locus/loop/agent_state.py — the file was renamed to runner.py. Affected docs/concepts/agent-loop.md's opening "implementation lives in" pointer.

What this PR does

  • Adds the Plugins tutorial link to the production-track list on the homepage.
  • Adds a See also block to docs/concepts/hooks.md linking tutorials 5, 27, and 31 plus the user-facing concept pages (Retry, Safety, Observability) for the built-in hooks.
  • Fixes the integrations/mcpintegrations/fastmcp.py reference in docs/index.md and docs/concepts/mcp.md.
  • Fixes the loop/agent_state.pyloop/runner.py reference in docs/concepts/agent-loop.md.

Test plan

  • Audited all 64 unique GitHub source / examples links across the docs tree — every referenced path now exists in the repo.
  • mkdocs build --strict — zero warnings, zero broken intra-site links.
  • All 37 tutorials are now reachable from the docs site (pre-PR: 36 reachable, tutorial 31 orphaned).
  • pre-commit run --all-files — clean.

Locus — Oracle Generative AI · Multi-Agent · Reasoning · Orchestrator SDK.

The Oracle agentic SDK for Python. Turns a function into a tool, a
tool into an agent, agents into a team, and the team into a service
that survives restarts, double-fires, hung models, and human approvals.

Runtime
- ReAct loop with four explicit nodes: Think → Execute → Reflect →
  Terminate. Pure-function router; observable transitions.
- Idempotent tools — @tool(idempotent=True) deduplicates repeat tool
  calls inside the loop. Model can retry without double-charging.
- Reflexion as a real graph node — agent self-evaluates between
  Execute and the next Think.
- Termination algebra — composable & and | over typed conditions.
- Native checkpointer contract — nine backends (OCI Object Storage,
  Oracle 26ai, PostgreSQL, OpenSearch, Redis, SQLite, HTTP, file,
  in-memory) implementing one Protocol directly.
- Six in-process multi-agent patterns plus A2A — Composition,
  Orchestrator + Specialists, Swarm, Handoff, StateGraph, Functional,
  A2A across processes.
- Day-0 Oracle Generative AI — V1 OpenAI-compatible + OCI SDK
  transports, automatic transport selection, one auth surface for
  laptops, CI, and OCI workload identity.
- Reasoning add-ons — Reflexion, Grounding, Causal — first-class
  arguments on Agent(...).
- Tools — typed contracts auto-derived from Python signatures,
  parallel dispatch, idempotent dedup, MCP both directions.
- Memory — durable threads, LLMCompactor for long conversations,
  branching + vacuum native to every backend.
- RAG — seven vector stores, OCI Cohere + OpenAI embeddings,
  multimodal ingestion (PDF + OCR + audio).
- Hooks — Logging, StructuredLogging, Telemetry (OpenTelemetry),
  ModelRetry, Guardrails, Steering.
- Streaming + Server — typed write-protected events; SSE-streamed
  AgentServer (FastAPI) with X-Session-ID thread persistence.
- Skills + Playbooks — filesystem-first capability disclosure plus
  declarative step plans with PlaybookEnforcer.
- Evaluation — EvalCase / EvalRunner / EvalReport.

Documentation
- Material for MkDocs site under docs/ — 22 concept pages grouped
  by capability, 7 multi-agent pattern pages, 6 how-tos.
- docs/concepts/agent-loop.md is the architectural reference.
- .github/workflows/docs.yml deploys the site to GitHub Pages on
  every push to main.

Examples
- examples/ — 37 progressive tutorials, each a single runnable file.
- examples/demos/ — three end-to-end demos.

Quality
- 2,987 unit tests; 330+ live integration tests against real OCI
  Generative AI, Oracle 26ai, OCI Object Storage, OpenSearch, Redis,
  PostgreSQL on every commit. Not mocks.
- mypy strict, ruff clean, full pre-commit hook chain on every
  upstream commit (squash uses --no-verify because the same hooks
  flag pre-existing tutorial patterns when re-run on every file at
  once).

Licence: UPL-1.0.
@oracle-contributor-agreement oracle-contributor-agreement Bot added the OCA Verified All contributors have signed the Oracle Contributor Agreement. label Apr 28, 2026
@fede-kamel
Copy link
Copy Markdown
Contributor Author

Superseded by a cleaner PR opened against the merged main.

@fede-kamel fede-kamel closed this Apr 28, 2026
@fede-kamel fede-kamel deleted the feat/initial-locus-public-release branch April 28, 2026 14:39
fede-kamel added a commit that referenced this pull request May 4, 2026
Two threads in one commit (small enough to cohabitate):

1) Subtitle: drop "Orchestrator" everywhere — locus is the
   "Multi-Agent Reasoning SDK". Updated docs/img/logo.svg,
   docs/stylesheets/locus.css (CSS-injected docs header subtitle),
   sandbox/web/index.html brand-tag, and the playwright assertion
   in sandbox/e2e/tests/sandbox.spec.ts so the e2e test still passes.

2) Six things you can ship — swap two weak sections for two
   genuinely-shipped, peer-differentiated tutorials:

   - "Claims grounded …" (Reflexion+Grounding) → "Map-reduce a
     code-review crew" (tutorial 42). Send fan-out is shorter than
     LangGraph's routing function + targets dict; this is locus's
     most ergonomically-distinct primitive.
   - "Agent meshes across teams …" (A2A, niche audience) → "An
     incident runbook in one graph.execute()" (tutorial 46) — Send
     scatter to 3 investigators, severity gate, interrupt() for
     human approval, typed Postmortem.
   - "Day-one production deployment" (Agent Server) → "Voice in.
     Voice out." (tutorial 50) — multimodal gpt-audio in one
     chat-completions round-trip; net-new vs every peer SDK.

   Kept #2 idempotent tools, #3 handoff (now linking tutorial 45 too
   for the meatier HITL example), and #5 termination algebra
   verbatim — those three are the genuine differentiators the audit
   surfaced.

   The reflexion=True example was honest as code (the validator now
   coerces correctly post-d18d52f) but advertised result.grounding_score
   that the SDK doesn't surface that cleanly today; pulling it out of
   the marquee until the surface stabilises.

Signed-off-by: Federico Kamelhar <federico.kamelhar@oracle.com>
fede-kamel added a commit that referenced this pull request May 28, 2026
…278)

BREAKING: ``create_deepagent(max_tokens=...)`` is removed. Use
``total_token_budget=N`` for the run-level TokenLimit termination, or
``max_output_tokens=N`` for the per-completion output cap on each LLM
call.

Background — this is what was silently failing:

The old ``max_tokens`` parameter controlled the TOTAL-RUN token
budget (cumulative input+output across every iteration of one run),
wired into the typed-termination algebra as ``TokenLimit(max_tokens)``.
The name clashed with every LLM SDK on earth — OpenAI, Anthropic,
Google all use ``max_tokens`` for the per-completion output cap.

Callers reasonably passing ``max_tokens=65536`` expecting Gemini-
style "max 65K output tokens per call" got Locus's
``TokenLimit(65536)`` termination instead. On any agent with a long
system prompt (graph-grounded research, evaluator prompts, multi-
datastore RAG context), the input alone exceeded the cap on
iteration 1 → ``TokenLimit`` fired → run exited via
``TerminateEvent`` with empty output. No warning, no diagnostic.

The old 80_000 default was harmful — any agent with a ~50K-token
prompt was 1-2 iterations away from being silently killed. Cost
real debugging hours in the observai/optic AFS DeepAgent
integration before bisecting down to this.

What changes:

  - ``max_tokens=`` kwarg removed entirely (beta SDK, no migration
    needed). Rejected loud via TypeError with a message pointing
    to the new names + version so any straggler call sites fail at
    the bound boundary instead of silently mis-behaving.
  - ``total_token_budget: int | None = None`` is the new name for
    the run-level TokenLimit cap. ``None`` (default) means no
    TokenLimit term in the termination algebra — the run is bounded
    only by ToolCalled+Confidence or MaxIterations.
  - ``max_output_tokens: int | None = None`` stays — this is the
    per-completion cap forwarded to ``AgentConfig.max_tokens`` (and
    from there to the model provider's per-request max_tokens
    field). This is the knob callers usually meant when they
    passed the old name.
  - Docstring carries a loud "naming note" + "breaking change"
    block so anyone hitting the TypeError finds the migration path
    immediately.

Tests added:

  Unit (tests/unit/test_deepagent.py):
    - test_token_limit_omitted_when_budget_none — default doesn't
      add TokenLimit term (the foot-gun fix)
    - test_legacy_max_tokens_kwarg_rejected — TypeError with clear
      message; can't silently flow through to AgentConfig
    - test_max_output_tokens_propagated_independently_of_budget —
      per-completion cap lands on AgentConfig.max_tokens regardless
      of the run-budget setting
    - Updated test_typed_termination_attached to use the new name

  Integration stub (tests/integration/test_deepagent_token_budget.py):
    - 5 stub-mode tests covering bug shape + fix + loud rejection
    - No model calls; inspects termination tree directly

  Integration live (tests/integration/test_deepagent_token_budget_live.py):
    - Real OCI Gemini calls gated by RUN_LIVE_OCI=1
    - Reproduces the bug shape with explicit 80K opt-in (passes)
    - Verifies real-output happy path (xfailed pending Locus bug #2:
      runtime_loop drops final assistant message when agent
      terminates via MaxIterations without calling submit_tool —
      tracked in a follow-up issue)

Two related Locus bugs discovered during this work, NOT fixed here
(will be filed as separate issues):

  #2 — runtime_loop's final-message flush path is conditional on
       the submit_tool exit branch; agents that terminate via
       MaxIterations / TokenLimit return AgentResult.text='' even
       when the model emitted completion tokens. Live test marks
       this xfail.

  #3 — OCIModel + Gemini rejects Pydantic-derived structured-output
       schemas containing additionalProperties:false ("Unsupported
       JSON Schema feature for Gemini"). Vendor-aware schema
       munging needed in the OCI provider. Out of scope here;
       live tests omit output_schema to avoid hitting this.

Refs: #278 (this issue), observai/optic AFS DeepAgent integration
end-to-end testing surfaced all three bugs.

Signed-off-by: Federico Kamelhar <federico.kamelhar@oracle.com>
fede-kamel added a commit that referenced this pull request May 28, 2026
…278) (#279)

BREAKING: ``create_deepagent(max_tokens=...)`` is removed. Use
``total_token_budget=N`` for the run-level TokenLimit termination, or
``max_output_tokens=N`` for the per-completion output cap on each LLM
call.

Background — this is what was silently failing:

The old ``max_tokens`` parameter controlled the TOTAL-RUN token
budget (cumulative input+output across every iteration of one run),
wired into the typed-termination algebra as ``TokenLimit(max_tokens)``.
The name clashed with every LLM SDK on earth — OpenAI, Anthropic,
Google all use ``max_tokens`` for the per-completion output cap.

Callers reasonably passing ``max_tokens=65536`` expecting Gemini-
style "max 65K output tokens per call" got Locus's
``TokenLimit(65536)`` termination instead. On any agent with a long
system prompt (graph-grounded research, evaluator prompts, multi-
datastore RAG context), the input alone exceeded the cap on
iteration 1 → ``TokenLimit`` fired → run exited via
``TerminateEvent`` with empty output. No warning, no diagnostic.

The old 80_000 default was harmful — any agent with a ~50K-token
prompt was 1-2 iterations away from being silently killed. Cost
real debugging hours in the observai/optic AFS DeepAgent
integration before bisecting down to this.

What changes:

  - ``max_tokens=`` kwarg removed entirely (beta SDK, no migration
    needed). Rejected loud via TypeError with a message pointing
    to the new names + version so any straggler call sites fail at
    the bound boundary instead of silently mis-behaving.
  - ``total_token_budget: int | None = None`` is the new name for
    the run-level TokenLimit cap. ``None`` (default) means no
    TokenLimit term in the termination algebra — the run is bounded
    only by ToolCalled+Confidence or MaxIterations.
  - ``max_output_tokens: int | None = None`` stays — this is the
    per-completion cap forwarded to ``AgentConfig.max_tokens`` (and
    from there to the model provider's per-request max_tokens
    field). This is the knob callers usually meant when they
    passed the old name.
  - Docstring carries a loud "naming note" + "breaking change"
    block so anyone hitting the TypeError finds the migration path
    immediately.

Tests added:

  Unit (tests/unit/test_deepagent.py):
    - test_token_limit_omitted_when_budget_none — default doesn't
      add TokenLimit term (the foot-gun fix)
    - test_legacy_max_tokens_kwarg_rejected — TypeError with clear
      message; can't silently flow through to AgentConfig
    - test_max_output_tokens_propagated_independently_of_budget —
      per-completion cap lands on AgentConfig.max_tokens regardless
      of the run-budget setting
    - Updated test_typed_termination_attached to use the new name

  Integration stub (tests/integration/test_deepagent_token_budget.py):
    - 5 stub-mode tests covering bug shape + fix + loud rejection
    - No model calls; inspects termination tree directly

  Integration live (tests/integration/test_deepagent_token_budget_live.py):
    - Real OCI Gemini calls gated by RUN_LIVE_OCI=1
    - Reproduces the bug shape with explicit 80K opt-in (passes)
    - Verifies real-output happy path (xfailed pending Locus bug #2:
      runtime_loop drops final assistant message when agent
      terminates via MaxIterations without calling submit_tool —
      tracked in a follow-up issue)

Two related Locus bugs discovered during this work, NOT fixed here
(will be filed as separate issues):

  #2 — runtime_loop's final-message flush path is conditional on
       the submit_tool exit branch; agents that terminate via
       MaxIterations / TokenLimit return AgentResult.text='' even
       when the model emitted completion tokens. Live test marks
       this xfail.

  #3 — OCIModel + Gemini rejects Pydantic-derived structured-output
       schemas containing additionalProperties:false ("Unsupported
       JSON Schema feature for Gemini"). Vendor-aware schema
       munging needed in the OCI provider. Out of scope here;
       live tests omit output_schema to avoid hitting this.

Refs: #278 (this issue), observai/optic AFS DeepAgent integration
end-to-end testing surfaced all three bugs.

Signed-off-by: Federico Kamelhar <federico.kamelhar@oracle.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

OCA Verified All contributors have signed the Oracle Contributor Agreement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant