diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000..cdd67dce --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,61 @@ +name: docs + +# Build the MkDocs site and deploy it to GitHub Pages. +# +# One-time manual step (cannot be automated from here): +# Repo Settings → Pages → Build and deployment → Source: "GitHub Actions". +# After that, every push to main that touches the docs rebuilds and deploys to +# https://fireflyframework.github.io/fireflyframework-agentic/ + +on: + push: + branches: [main] + paths: + - "docs/**" + - "overrides/**" + - "mkdocs.yml" + - "CHANGELOG.md" + - ".github/workflows/docs.yml" + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +# Allow one concurrent deployment; don't cancel an in-progress run. +concurrency: + group: pages + cancel-in-progress: false + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.13" + - name: Cache pip + uses: actions/cache@v4 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('docs/requirements.txt') }} + restore-keys: ${{ runner.os }}-pip- + - name: Install docs toolchain + run: pip install -r docs/requirements.txt + - name: Build (strict) + run: mkdocs build --strict + - uses: actions/upload-pages-artifact@v3 + with: + path: site + + deploy: + needs: build + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - id: deployment + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index d4966a8d..c91f4ecf 100644 --- a/.gitignore +++ b/.gitignore @@ -144,3 +144,9 @@ examples/corpus_search/test_queries.md examples/corpus_search/test_queries.local.md docs/superpowers/ PLAYGROUND.md + +# MkDocs build output +/site/ + +# Playwright MCP screenshots (local verification) +/.playwright-mcp/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6c3d2a5e..eb0c5096 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -34,6 +34,10 @@ repos: args: [--markdown-linebreak-ext=md] - id: end-of-file-fixer - id: check-yaml + # mkdocs.yml uses Material's `!!python/name:` tags (e.g. the mermaid + # superfence), which check-yaml can't construct. `mkdocs build --strict` + # in the docs workflow is its real validator. + exclude: ^mkdocs\.yml$ - id: check-toml - id: check-json # tsconfig*.json files use JSONC (comments, trailing commas). diff --git a/CHANGELOG.md b/CHANGELOG.md index 0307b7e6..76d8cbe4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -343,7 +343,7 @@ a **live Anthropic model** end to end. All nine confirmed P0/P1 findings address Framework alignment: the Dynamic Workflows engine and the tools system now run on the framework's own primitives and on pydantic-ai's native model — no parallel implementations, no lossy shims. Includes breaking changes; see the -[Migration Guide](docs/migration.md). +[Migration Guide](https://github.com/fireflyframework/fireflyframework-agentic/blob/main/docs/migration.md). ### Changed (BREAKING) diff --git a/README.md b/README.md index c0f7e592..341e81a0 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ You write your business logic; the framework provides the architecture. ## Architecture at a Glance

- Firefly Agentic architecture: one front door (pip install fireflyframework-agentic, @firefly_agent) over five layers — Orchestration, Experimentation, Intelligence, Agent, Core — on the Pydantic AI engine. + Firefly Agentic architecture: one front door (import fireflyframework_agentic, @firefly_agent) over five layers — Orchestration, Experimentation, Intelligence, Agent, Core — on the Pydantic AI engine.

### Protocol Hierarchy diff --git a/assets/architecture.svg b/assets/architecture.svg index 11db3546..26b50187 100644 --- a/assets/architecture.svg +++ b/assets/architecture.svg @@ -22,7 +22,7 @@ THE FRONT DOOR - pip install fireflyframework-agentic · @firefly_agent + import fireflyframework_agentic · @firefly_agent one install one decorator diff --git a/assets/tools/build_brand_assets.py b/assets/tools/build_brand_assets.py index c664e5c3..99bb96a2 100644 --- a/assets/tools/build_brand_assets.py +++ b/assets/tools/build_brand_assets.py @@ -219,7 +219,7 @@ def architecture(): b.append(f'') b.append(f'') b.append(f'THE FRONT DOOR') - b.append(f'pip install fireflyframework-agentic · @firefly_agent') + b.append(f'import fireflyframework_agentic · @firefly_agent') b.append(f'one install') b.append(f'one decorator') b.append(f''+"".join(f'' for f in (.18,.45,.72))+'') diff --git a/docs/agents.md b/docs/agents.md index ef3aa5df..9b0fa2c1 100644 --- a/docs/agents.md +++ b/docs/agents.md @@ -88,7 +88,7 @@ agent = FireflyAgent(name="analyst", model=model) ``` This also works with the `@firefly_agent` decorator and all template agents. See the -[tutorial](tutorial.md#model-providers--authentication) for full provider coverage +[tutorial](tutorial.md#model-providers-authentication) for full provider coverage including Azure OpenAI, Anthropic, Google, and OpenAI-compatible endpoints. ### Model settings & default temperature @@ -1153,4 +1153,4 @@ export OPENAI_API_KEY="sk-..." uv run python examples/basic_agent.py ``` -See [examples/README.md](../examples/README.md) for the full list. +See [examples/README.md](https://github.com/fireflyframework/fireflyframework-agentic/blob/main/examples/README.md) for the full list. diff --git a/docs/architecture.md b/docs/architecture.md index 38aee92f..60af19f5 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -590,13 +590,13 @@ the framework adds on top is built to be provider-uniform: (those backends cache differently). See [Agents → PromptCacheMiddleware](agents.md#promptcachemiddleware). - **Tool schemas** — real `python_type`s keep tool schemas portable, with one caveat: **Gemini rejects free-form `dict[str, Any]` object schemas** — use a JSON - string or a nested model instead. See [Tools](tools.md#full-fidelity-schemas--runcontext). + string or a nested model instead. See [Tools](tools.md#full-fidelity-schemas-runcontext). - **Failover & rate limits** — `FallbackModelWrapper` / `run_with_fallback` fail over across providers, and rate-limit backoff prefers a provider's structured retry hint (e.g. Gemini `retry_delay`) before falling back to exponential backoff. This is validated end-to-end against a real provider by -`tests/integration/test_real_anthropic_e2e.py` (nightly; see [tests/README](../tests/README.md)). +`tests/integration/test_real_anthropic_e2e.py` (nightly; see [tests/README](https://github.com/fireflyframework/fireflyframework-agentic/blob/main/tests/README.md)). --- diff --git a/docs/assets/agent-anatomy.svg b/docs/assets/agent-anatomy.svg new file mode 100644 index 00000000..92c2bcb1 --- /dev/null +++ b/docs/assets/agent-anatomy.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + Anatomy of an agent run — middleware all the way down + fireflyframework-agentic + + FireflyAgent wraps pydantic_ai.Agent; a composable MiddlewareChain wraps every run. + MiddlewareChain — wraps every agent.run() + + Logging + + Observability + + PromptGuard + + OutputGuard + + CostGuard + + Cache + + PromptCache + + Explainability + + Validation + + Retry + + CircuitBreaker + + + FireflyAgent -> pydantic_ai.Agent + the model call — tools, structured output, streaming + + DelegationRouter7 strategies route across an agent pool + FallbackModelWrapper · ResultCacheautomatic failover + response caching + MemoryManager · AgentLifecycleconversation + working memory · hooks + diff --git a/docs/assets/architecture.svg b/docs/assets/architecture.svg new file mode 100644 index 00000000..26b50187 --- /dev/null +++ b/docs/assets/architecture.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + Architecture at a glance + fireflyframework-agentic + + One install, one decorator — five cohesive layers on the Pydantic AI engine. + + + THE FRONT DOOR + import fireflyframework_agentic · @firefly_agent + one install + one decorator + + + DEPENDS ON + + 1 + Orchestration + (2 modules) + pipeline (DAG · 9 steps · checkpointer) · workflows (dynamic DSL · journal · routing) + + 2 + Experimentation + (2 modules) + experiments · lab — optional leaf modules + + 3 + Intelligence + (4 modules) + reasoning · validation/QoS · observability · explainability + + 4 + Agent + (6 modules) + agents · tools · prompts · memory · content · embeddings/vectorstores + + 5 + Core + (7 modules) + BASE LAYER + config · protocols · exceptions · plugins · resilience · storage · security + + + Pydantic AI engine + pydantic-ai · pydantic — the type-safe agent core every layer builds on + Agent · Tool · RunContext + Embeddings (8 providers) · Vector Stores (6 backends) — a cross-cutting RAG capability wired into the Agent & Orchestration layers. + diff --git a/docs/assets/banner.svg b/docs/assets/banner.svg new file mode 100644 index 00000000..1f9d397f --- /dev/null +++ b/docs/assets/banner.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + agentic + + + Production-grade agents, reasoning & pipelines + type-safe · model-agnostic · built on Pydantic AI · async-native + fireflyframework-agentic + diff --git a/docs/assets/ecosystem.svg b/docs/assets/ecosystem.svg new file mode 100644 index 00000000..e09c8e7f --- /dev/null +++ b/docs/assets/ecosystem.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + One framework, every runtime — the Firefly family + fireflyframework-agentic + + Firefly Agentic is the agentic member of a polyglot platform that shares one programming model. + + + + + + + + + + + FRAMEWORK + one model · many runtimes + + + Java / Spring Boot + 40+ modules · Production + + + .NET + CalVer · Beta + + + PyFly + Python · 39 modules + + + Rust + tokio + axum · Active + + + Go + CLI · Active + + + Frontend + Angular · flyfront + + + Agentic + agents · reasoning · RAG + + you are here + diff --git a/docs/assets/favicon.svg b/docs/assets/favicon.svg new file mode 100644 index 00000000..600f3d0f --- /dev/null +++ b/docs/assets/favicon.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/assets/logo.svg b/docs/assets/logo.svg new file mode 100644 index 00000000..1fe31a05 --- /dev/null +++ b/docs/assets/logo.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/assets/pipeline.svg b/docs/assets/pipeline.svg new file mode 100644 index 00000000..2c1df623 --- /dev/null +++ b/docs/assets/pipeline.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + Pipelines — a typed DAG your agents run on + fireflyframework-agentic + + PipelineEngine runs nodes level-by-level via asyncio.gather; per-node conditions, retries and timeouts. + ingestBinaryNormalizer + + splitDocumentSplitter + + classifyAgentStep + + extractAgentStep × N + + validateOutputReviewer + + assembleFanInStep + + explainReportBuilder + FanOutStep -> parallel -> FanInStep + + + + + human-in-the-loop · Pause / Send + Checkpointer · FileCheckpointerpersist & resume long runs · CheckpointRecord + AuditLog familyFile · Logging · Otel · Queryable (AuditEntry) + PipelineBuilder.chain(...) wires the DAG · AgentStep · ReasoningStep · CallableStep · BranchStep · BatchLLMStep · EmbeddingStep · RetrievalStep + diff --git a/docs/assets/protocols.svg b/docs/assets/protocols.svg new file mode 100644 index 00000000..41425287 --- /dev/null +++ b/docs/assets/protocols.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + Protocol-driven contracts — 28 ports, swap any part + fireflyframework-agentic + + Every extension point is a @runtime_checkable Protocol or ABC — implement it and the framework discovers you by duck typing. + Agent · ToolsAgentLikeToolProtocolGuardProtocolDelegationStrategyAgentMiddleware + IntelligenceReasoningPatternValidationRule + OrchestrationStepExecutorCheckpointerAuditLogQueryableAuditLogEventHandlerPipelineEventHandler + Workflows (new)AgentRunnerStreamingAgentRunnerJournalBackendModelSelectionStrategy + Content · MemoryChunkerCompressionStrategyContentSourceOfficeConverterMemoryStore + Embeddings · Security · ExecEmbeddingProtocolVectorStoreProtocolScopedVectorStoreEncryptionProviderCostSinkExecutionEnvironment + diff --git a/docs/assets/rag.svg b/docs/assets/rag.svg new file mode 100644 index 00000000..92e8fb36 --- /dev/null +++ b/docs/assets/rag.svg @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + Retrieval-augmented — eight embedders × six vector stores, one API + fireflyframework-agentic + + EmbeddingProtocol and VectorStoreProtocol make providers and backends fully swappable. + EMBEDDERS + + OpenAI + + Azure OpenAI + + Cohere + + Google + + Mistral + + Voyage AI + + AWS Bedrock + + Ollama + EmbeddingProtocol · BaseEmbedder + VECTOR STORES + + InMemory + + ChromaDB + + Pinecone + + Qdrant + + pgvector + + sqlite-vec + VectorStoreProtocol · BaseVectorStore + textraw documents + + embedBaseEmbedder + + upsertauto-embed + + search_textquery · top_k + + SearchResultscored hits + + + ScopedVectorStore / TenantScopedVectorStore isolate per tenant · EmbeddingStep / RetrievalStep drop straight into pipelines + diff --git a/docs/assets/reasoning.svg b/docs/assets/reasoning.svg new file mode 100644 index 00000000..44beba11 --- /dev/null +++ b/docs/assets/reasoning.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + Six reasoning patterns on one pluggable loop + fireflyframework-agentic + + Every pattern fills the same template-method loop; ReasoningPipeline chains them and OutputReviewer validates. + _reason + + _act + + _observe + + _should_continue + + + loops until done -> ReasoningResult + ReasoningTrace + ReActobserve -> think -> actinterleaved tool use + Chain of Thoughtstep-by-step reasoningexplicit intermediate steps + Plan-and-Executegoal -> plan -> stepsoptional replanning + Reflexionexecute -> critique -> retryself-correcting loop + Tree of Thoughtsbranch -> evaluate -> selectsearch over thoughts + Goal Decompositiongoal -> phases -> taskshierarchical breakdown + diff --git a/docs/assets/workflows.svg b/docs/assets/workflows.svg new file mode 100644 index 00000000..9e2a5910 --- /dev/null +++ b/docs/assets/workflows.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + Dynamic Workflows — a code-defined DSL over your agents + fireflyframework-agentic + + @workflow async functions orchestrate agents deterministically — a complement to the declarative pipeline DAG. + @workflow · @subworkflow · run_workflowasync def flow(args) -> OutputT: … + + DSL PRIMITIVES + + agent() + + parallel() + + pipeline() + + stream() + + phase() + + human() + + map_agents() + + log() + + + WorkflowContext + current_workflow() — carries budget · journal · runner · event handler + + Runner · AgentRunnerFireflyAgentRunner — defaultDefaultAgentRunner — lightmiddleware · guards · budget + + Journal · JournalBackendFileJournalBackenddeterministic resumereplays completed calls + + WorkflowBudgetconcurrency capagent-count ceilingtoken / cost ceiling + + Routing · ModelSelectionSmartRoutingRunnerComplexityHeuristicStrategyCostFloorStrategy + Verification helpers (refute-by-default)cascade · adversarial_verify · judge_panel · loop_until_dry + Code-defined & deterministic (native Python control flow) — coexists with the declarative pipeline DAG in the Orchestration layer. + diff --git a/docs/changelog.md b/docs/changelog.md new file mode 100644 index 00000000..d0506c4b --- /dev/null +++ b/docs/changelog.md @@ -0,0 +1,6 @@ +--- +title: Changelog +description: Notable changes to Firefly Agentic, by version. +--- + +--8<-- "CHANGELOG.md" diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md new file mode 100644 index 00000000..0ab671cc --- /dev/null +++ b/docs/getting-started/installation.md @@ -0,0 +1,81 @@ +--- +title: Installation +description: Install Firefly Agentic with the interactive installer, uv, or pip — and pick only the extras your deployment needs. +--- + +# Installation + +## Requirements + +- **Python 3.13** or later +- [uv](https://docs.astral.sh/uv/) (recommended) or pip +- At least one LLM provider key — `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, + `GEMINI_API_KEY`, `GROQ_API_KEY`, or any + [Pydantic AI-supported provider](https://ai.pydantic.dev/models/). + +## One-line installer (recommended) + +The interactive installer detects your platform, checks Python and uv, lets you +choose extras, and verifies the result. + +=== "macOS / Linux" + + ```bash + curl -fsSL https://raw.githubusercontent.com/fireflyframework/fireflyframework-agentic/main/install.sh | bash + ``` + +=== "Windows (PowerShell)" + + ```powershell + irm https://raw.githubusercontent.com/fireflyframework/fireflyframework-agentic/main/install.ps1 | iex + ``` + +## From source + +```bash +git clone https://github.com/fireflyframework/fireflyframework-agentic.git +cd fireflyframework-agentic +uv sync --all-extras # or: pip install -e ".[all]" +``` + +## Optional extras + +Heavy libraries are pip extras, imported lazily so you install only what you +deploy. + +| Extra | What it adds | When you need it | +|---|---|---| +| `security` | cryptography | At-rest encryption (`EncryptedMemoryStore`, `AESEncryptionProvider`) | +| `script-execution` | pydantic-monty | The deny-by-default Monty sandbox for secure script execution | +| `embeddings` | numpy | Fast in-memory vector math | +| `openai-embeddings` | openai | OpenAI / Azure text embeddings | +| `cohere-embeddings` · `google-embeddings` · `mistral-embeddings` · `voyage-embeddings` · `bedrock-embeddings` · `ollama-embeddings` | provider SDKs | The matching embedding provider | +| `vectorstores-chroma` · `vectorstores-pinecone` · `vectorstores-qdrant` · `vectorstores-pgvector` · `vectorstores-sqlite-vec` | backend clients | The matching vector-store backend | +| `postgres` · `mongodb` | asyncpg/SQLAlchemy · motor/pymongo | Database-backed memory / storage | +| `binary` | pypdf, Pillow, pillow-heif, cairosvg, py7zr, extract-msg | `content.binary` file normalisation | +| `watch` | watchfiles | File-watching for content sources | +| `all` | Everything above | Full install with all integrations | + +## Verify + +```bash +python -c "import fireflyframework_agentic; print(fireflyframework_agentic.__version__)" +``` + +## Uninstall + +=== "macOS / Linux" + + ```bash + curl -fsSL https://raw.githubusercontent.com/fireflyframework/fireflyframework-agentic/main/uninstall.sh | bash + ``` + +=== "Windows (PowerShell)" + + ```powershell + irm https://raw.githubusercontent.com/fireflyframework/fireflyframework-agentic/main/uninstall.ps1 | iex + ``` + +--- + +Next: the **[5-Minute Quick Start](quickstart.md)** → diff --git a/docs/getting-started/jupyter.md b/docs/getting-started/jupyter.md new file mode 100644 index 00000000..da035952 --- /dev/null +++ b/docs/getting-started/jupyter.md @@ -0,0 +1,81 @@ +--- +title: Jupyter Notebooks +description: Firefly Agentic is async-first, so await works directly in notebook cells — no asyncio.run() or nest_asyncio needed. +--- + +# Using in Jupyter Notebooks + +Firefly Agentic works seamlessly in Jupyter and JupyterLab. Because the framework +is async-first, use `await` directly in cells — Jupyter provides a running event +loop automatically. + +## Setup + +```bash +cd fireflyframework-agentic +source .venv/bin/activate # the venv created by the installer +pip install ipykernel +python -m ipykernel install --user --name fireflyagentic --display-name "Firefly Agentic" +jupyter lab # or: jupyter notebook +``` + +Then select the **Firefly Agentic** kernel when creating a new notebook. + +## Example notebook + +```python +# Cell 1 — configure +import os +os.environ["OPENAI_API_KEY"] = "sk-..." # or set in .env +os.environ["FIREFLY_AGENTIC_DEFAULT_MODEL"] = "openai:gpt-4o" +``` + +```python +# Cell 2 — create an agent +from fireflyframework_agentic.agents import FireflyAgent + +agent = FireflyAgent(name="notebook-bot", model="openai:gpt-4o") +result = await agent.run("Explain quantum entanglement in two sentences.") +print(result.output) +``` + +```python +# Cell 3 — memory for multi-turn conversations +from fireflyframework_agentic.memory import MemoryManager + +memory = MemoryManager(max_conversation_tokens=32_000) +agent_with_mem = FireflyAgent(name="chat", model="openai:gpt-4o", memory=memory) + +cid = memory.new_conversation() +await agent_with_mem.run("My name is Alice.", conversation_id=cid) +result = await agent_with_mem.run("What is my name?", conversation_id=cid) +print(result.output) # Alice +``` + +```python +# Cell 4 — reasoning patterns +from fireflyframework_agentic.reasoning import ReActPattern + +react = ReActPattern(max_steps=5) +result = await react.execute(agent, "What are the top 3 uses of Python in 2026?") +print(result.output) +``` + +```python +# Cell 5 — structured output with validation +from pydantic import BaseModel +from fireflyframework_agentic.validation import OutputReviewer + +class Summary(BaseModel): + title: str + bullet_points: list[str] + confidence: float + +reviewer = OutputReviewer(output_type=Summary, max_retries=2) +result = await reviewer.review(agent, "Summarize the benefits of async Python.") +result.output # displays the structured Summary object in the notebook +``` + +!!! tip + You do not need `asyncio.run()` or `nest_asyncio` in Jupyter — `await` works at + the top level of any cell because Jupyter runs its own event loop. diff --git a/docs/getting-started/quickstart.md b/docs/getting-started/quickstart.md new file mode 100644 index 00000000..1ad7d068 --- /dev/null +++ b/docs/getting-started/quickstart.md @@ -0,0 +1,136 @@ +--- +title: Quick Start +description: Configure a provider, define an agent, add memory, reason, validate and wire a pipeline — in five minutes. +--- + +# 5-Minute Quick Start + +This is the shape of the framework end to end. For the full, hands-on path, see +**[The Complete Tutorial](../tutorial.md)**. + +## 1. Configure + +Create a `.env` file (or set environment variables): + +```bash +# Provider API key (Pydantic AI reads these automatically) +OPENAI_API_KEY=sk-... +# ANTHROPIC_API_KEY=sk-ant-... +# GEMINI_API_KEY=... + +# Framework settings +FIREFLY_AGENTIC_DEFAULT_MODEL=openai:gpt-4o +FIREFLY_AGENTIC_DEFAULT_TEMPERATURE=0.3 +``` + +The model string is `"provider:model_name"` — e.g. `"openai:gpt-4o"`, +`"anthropic:claude-sonnet-4-20250514"`, `"google:gemini-2.0-flash"`. For +programmatic credentials (Azure, Bedrock, custom endpoints), pass a Pydantic AI +`Model` object to `FireflyAgent(model=...)` — see the +[tutorial](../tutorial.md#model-providers-authentication). + +## 2. Define an agent + +```python +from fireflyframework_agentic.agents import firefly_agent + +@firefly_agent(name="assistant", model="openai:gpt-4o") +def assistant_instructions(ctx): + return "You are a helpful conversational assistant." +``` + +## 3. Register a tool + +```python +from fireflyframework_agentic.tools import firefly_tool + +@firefly_tool(name="lookup", description="Look up a term") +async def lookup(query: str) -> str: + return f"Result for {query}" +``` + +!!! tip "Human-in-the-loop" + Mark a tool `@firefly_tool(name=..., requires_approval=True)` and the agent run + **pauses** before executing it — `run()` returns a `DeferredToolRequests` + (detect with `is_deferred(result)`). Resume with + `agent.run(message_history=paused.all_messages(), deferred_tool_results=...)`. + Full detail in [Tools → Human-in-the-loop](../tools.md#human-in-the-loop-tool-approval). + +## 4. Add memory for multi-turn conversations + +```python +from fireflyframework_agentic.agents import FireflyAgent +from fireflyframework_agentic.memory import MemoryManager + +memory = MemoryManager(max_conversation_tokens=32_000) +agent = FireflyAgent(name="bot", model="openai:gpt-4o", memory=memory) + +cid = memory.new_conversation() +result = await agent.run("Hello!", conversation_id=cid) +result = await agent.run("What did I just say?", conversation_id=cid) +``` + +## 5. Apply a reasoning pattern + +```python +from fireflyframework_agentic.reasoning import ReActPattern + +react = ReActPattern(max_steps=5) +result = await react.execute(agent, "What is the weather in London?") +print(result.output) +``` + +## 6. Validate output + +```python +from pydantic import BaseModel +from fireflyframework_agentic.validation import OutputReviewer + +class Answer(BaseModel): + answer: str + confidence: float + +reviewer = OutputReviewer(output_type=Answer, max_retries=2) +result = await reviewer.review(agent, "What is 2+2?") +print(result.output) # Answer(answer="4", confidence=0.99) +``` + +## 7. Wire a pipeline + +```python +from fireflyframework_agentic.pipeline.builder import PipelineBuilder +from fireflyframework_agentic.pipeline.steps import AgentStep, CallableStep + +pipeline = ( + PipelineBuilder("my-pipeline") + .add_node("classify", AgentStep(classifier_agent)) + .add_node("extract", AgentStep(extractor_agent)) + .add_node("validate", CallableStep(validate_fn)) + .chain("classify", "extract", "validate") + .build() +) +result = await pipeline.run(inputs="Process this document") +``` + +## 8. Embed and search (RAG) + +```python +from fireflyframework_agentic.embeddings.providers import OpenAIEmbedder +from fireflyframework_agentic.vectorstores import InMemoryVectorStore, VectorDocument + +embedder = OpenAIEmbedder(model="text-embedding-3-small") +store = InMemoryVectorStore(embedder=embedder) + +await store.upsert([ + VectorDocument(id="1", text="Python is great for AI"), + VectorDocument(id="2", text="Rust is fast and safe"), +]) + +results = await store.search_text("machine learning languages", top_k=1) +print(results[0].document.text) # Python is great for AI +``` + +--- + +Next: **[The Complete Tutorial](../tutorial.md)** builds a full IDP pipeline from +scratch · or jump to the [Architecture](../architecture.md) overview. diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..4924b3cd --- /dev/null +++ b/docs/index.md @@ -0,0 +1,11 @@ +--- +title: Firefly Agentic +description: >- + The production-grade agentic metaframework, built on Pydantic AI. Keep + Pydantic AI's Agent, Tool and RunContext — gain lifecycle hooks, delegation, + memory, reasoning patterns, validation loops, RAG and DAG pipelines. +template: home.html +hide: + - navigation + - toc +--- diff --git a/docs/javascripts/constellation.js b/docs/javascripts/constellation.js new file mode 100644 index 00000000..33d6cc40 --- /dev/null +++ b/docs/javascripts/constellation.js @@ -0,0 +1,146 @@ +/* + * Firefly constellation — the landing-page signature. + * Amber fireflies drift through the dark; when they pass near one another a + * faint violet edge is drawn between them. Read it two ways at once: fireflies + * in the night, and a network of agents delegating. One ambient animation, + * nothing else moves. + * + * - Honours prefers-reduced-motion (renders a single static frame). + * - Pauses when the hero scrolls out of view. + * - Re-inits on Material's instant navigation. + */ +(function () { + "use strict"; + + function start() { + var canvas = document.getElementById("ff-constellation"); + if (!canvas || canvas.dataset.ffInit === "1") return; + canvas.dataset.ffInit = "1"; + + var ctx = canvas.getContext("2d"); + var reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches; + var host = canvas.parentElement; + var w = 0, h = 0, dpr = 1, nodes = [], raf = null, running = true; + var LINK = 150; + + function size() { + dpr = Math.min(window.devicePixelRatio || 1, 2); + w = host.clientWidth; + h = host.clientHeight; + canvas.width = Math.round(w * dpr); + canvas.height = Math.round(h * dpr); + ctx.setTransform(dpr, 0, 0, dpr, 0, 0); + } + + function seed() { + var count = Math.max(16, Math.min(46, Math.round((w * h) / 26000))); + nodes = []; + for (var i = 0; i < count; i++) { + nodes.push({ + x: Math.random() * w, + y: Math.random() * h, + vx: (Math.random() - 0.5) * 0.25, + vy: (Math.random() - 0.5) * 0.25, + r: Math.random() * 1.5 + 0.8, + p: Math.random() * Math.PI * 2 + }); + } + } + + function frame(t) { + ctx.clearRect(0, 0, w, h); + + // edges (the agent network) + for (var i = 0; i < nodes.length; i++) { + for (var j = i + 1; j < nodes.length; j++) { + var a = nodes[i], b = nodes[j]; + var dx = a.x - b.x, dy = a.y - b.y; + var d = Math.sqrt(dx * dx + dy * dy); + if (d < LINK) { + ctx.strokeStyle = "rgba(167,139,250," + (1 - d / LINK) * 0.22 + ")"; + ctx.lineWidth = 1; + ctx.beginPath(); + ctx.moveTo(a.x, a.y); + ctx.lineTo(b.x, b.y); + ctx.stroke(); + } + } + } + + // fireflies + for (var k = 0; k < nodes.length; k++) { + var n = nodes[k]; + if (!reduce) { + n.x += n.vx; n.y += n.vy; + if (n.x < 0 || n.x > w) n.vx *= -1; + if (n.y < 0 || n.y > h) n.vy *= -1; + } + var tw = reduce ? 0.85 : 0.55 + 0.45 * Math.sin(t * 0.001 + n.p); + var halo = ctx.createRadialGradient(n.x, n.y, 0, n.x, n.y, n.r * 6); + halo.addColorStop(0, "rgba(255,249,193," + 0.9 * tw + ")"); + halo.addColorStop(0.4, "rgba(246,168,33," + 0.5 * tw + ")"); + halo.addColorStop(1, "rgba(246,128,0,0)"); + ctx.fillStyle = halo; + ctx.beginPath(); + ctx.arc(n.x, n.y, n.r * 6, 0, 6.2832); + ctx.fill(); + ctx.fillStyle = "rgba(255,253,240," + 0.95 * tw + ")"; + ctx.beginPath(); + ctx.arc(n.x, n.y, n.r * 0.9, 0, 6.2832); + ctx.fill(); + } + + if (running && !reduce) raf = requestAnimationFrame(frame); + } + + function play() { + if (reduce) { frame(0); return; } + cancelAnimationFrame(raf); + raf = requestAnimationFrame(frame); + } + + size(); + seed(); + play(); + + if ("IntersectionObserver" in window) { + new IntersectionObserver(function (entries) { + entries.forEach(function (e) { + running = e.isIntersecting; + if (running) play(); else cancelAnimationFrame(raf); + }); + }).observe(canvas); + } + + var rt; + window.addEventListener("resize", function () { + clearTimeout(rt); + rt = setTimeout(function () { size(); seed(); if (reduce) frame(0); }, 200); + }); + } + + // Copy-to-clipboard for the install command. + function copyInstall() { + var btn = document.querySelector(".ff-install__copy"); + if (!btn || btn.dataset.ffBound === "1") return; + btn.dataset.ffBound = "1"; + btn.addEventListener("click", function () { + var cmd = btn.getAttribute("data-copy") || ""; + if (!navigator.clipboard) return; + navigator.clipboard.writeText(cmd).then(function () { + btn.classList.add("is-copied"); // CSS swaps the glyph; no innerHTML + setTimeout(function () { btn.classList.remove("is-copied"); }, 1400); + }); + }); + } + + function boot() { start(); copyInstall(); } + + if (window.document$ && typeof window.document$.subscribe === "function") { + window.document$.subscribe(boot); // Material instant navigation + } else if (document.readyState !== "loading") { + boot(); + } else { + document.addEventListener("DOMContentLoaded", boot); + } +})(); diff --git a/docs/pipeline.md b/docs/pipeline.md index 9c176978..0be16158 100644 --- a/docs/pipeline.md +++ b/docs/pipeline.md @@ -425,7 +425,7 @@ label; edges carrying a condition are annotated `if?`. | You want the engine to run independent nodes concurrently | You want resume-after-failure and start-from-middle semantics | | You're happy with `BranchStep` + per-node `condition` lambdas | You want one `.branch(...)` call and inspectable routing | -See [`examples/pipeline_state.py`](../examples/pipeline_state.py) for a +See [`examples/pipeline_state.py`](https://github.com/fireflyframework/fireflyframework-agentic/blob/main/examples/pipeline_state.py) for a runnable demo covering branching, software-factory checkpoint/resume, and map-reduce fan-out. diff --git a/docs/reasoning.md b/docs/reasoning.md index bf8098ab..668b1119 100644 --- a/docs/reasoning.md +++ b/docs/reasoning.md @@ -813,7 +813,7 @@ export OPENAI_API_KEY="sk-..." uv run python examples/reasoning_cot.py ``` -See [examples/README.md](../examples/README.md) for the full list. +See [examples/README.md](https://github.com/fireflyframework/fireflyframework-agentic/blob/main/examples/README.md) for the full list. ## Note: tool-using ReAct is implemented outside `reasoning/` diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 00000000..10eb19db --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,9 @@ +# Documentation toolchain for the Firefly Agentic site (MkDocs + Material). +# This file is the single source of truth for the GitHub Pages build +# (.github/workflows/docs.yml installs from it). Material vendors mkdocs and +# pymdown-extensions, so no other plugins are needed for the current site. +# +# Local preview: +# pip install -r docs/requirements.txt +# mkdocs serve +mkdocs-material>=9.5,<10 diff --git a/docs/stylesheets/firefly.css b/docs/stylesheets/firefly.css new file mode 100644 index 00000000..97cbb3de --- /dev/null +++ b/docs/stylesheets/firefly.css @@ -0,0 +1,551 @@ +/* ============================================================================= + Firefly Agentic — brand stylesheet + Loaded site-wide. Two responsibilities, kept separate: + 1. Docs theme: recolor Material to the exact violet brand (both schemes). + 2. Landing page: the immersive "firefly-in-the-dark" home, scoped under + .ff-home so nothing leaks into the docs. + Brand tokens are lifted verbatim from assets/README.md. + ========================================================================== */ + +@import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap"); + +:root { + /* Night sky */ + --ff-sky-0: #0b0a14; + --ff-sky-1: #120d1c; + --ff-sky-2: #140f1e; + --ff-ink: #1e1633; + /* Violet system */ + --ff-violet: #8b5cf6; + --ff-violet-bright: #a78bfa; + --ff-violet-2: #7c3aed; + --ff-violet-deep: #4c1d95; + --ff-violet-pale: #d6c6ff; + /* The one warm spark — the shared firefly */ + --ff-amber: #f6a821; + --ff-amber-hot: #f68000; + --ff-amber-pale: #fff9c1; + /* Text on dark */ + --ff-fg: #ece8f5; + --ff-muted: #b3a9cd; + --ff-faint: #8b82a3; + /* Surfaces */ + --ff-card: rgba(139, 92, 246, 0.05); + --ff-card-2: rgba(167, 139, 250, 0.08); + --ff-card-bd: rgba(167, 139, 250, 0.16); + --ff-card-bd-hot: rgba(167, 139, 250, 0.42); + /* Gradients */ + --ff-wm: linear-gradient(92deg, #d6c6ff 0%, #a78bfa 48%, #7c3aed 100%); + --ff-amber-grad: radial-gradient(circle at 50% 42%, #fffdf0, #fff6b0 45%, #f68000 100%); + --ff-header-h: 2.9rem; + --ff-display: "Space Grotesk", "Inter", system-ui, sans-serif; +} + +/* ============================================================================= + 1. DOCS — recolor Material to the brand (does not touch .ff-home) + ========================================================================== */ + +[data-md-color-scheme="default"] { + --md-primary-fg-color: #6d28d9; + --md-primary-fg-color--light: #8b5cf6; + --md-primary-fg-color--dark: #5b21b6; + --md-accent-fg-color: #7c3aed; + --md-typeset-a-color: #7c3aed; +} + +/* Slate, tinted toward violet so the dark docs feel like the same night sky. */ +[data-md-color-scheme="slate"] { + --md-hue: 264; + --md-primary-fg-color: #1c142e; + --md-primary-fg-color--light: #2a1f45; + --md-primary-fg-color--dark: #140e22; + --md-accent-fg-color: #a78bfa; + --md-typeset-a-color: #b89cff; + --md-default-bg-color: hsla(264, 24%, 9%, 1); +} + +/* Display face for all headings, in docs and on the landing. */ +.md-typeset h1, +.md-typeset h2, +.md-typeset h3, +.md-header__title { + font-family: var(--ff-display); + font-weight: 600; + letter-spacing: -0.01em; +} + +/* Brand-tinted code accents in docs admonitions/inline (subtle). */ +.md-typeset :not(pre) > code { + border-radius: 0.25rem; +} + +/* ============================================================================= + 2. LANDING — everything scoped under .ff-home (or body:has) + ========================================================================== */ + +/* Force the night sky behind the whole home document, both schemes, and hide + the empty Material main/sidebars (the landing lives in the tabs block). */ +body:has(.ff-home), +body:has(.ff-home) .md-container { + background-color: var(--ff-sky-0); +} +body:has(.ff-home) .md-main { display: none; } +body:has(.ff-home) .md-tabs { display: none; } + +/* Transparent header that melts into the hero, then solidifies on scroll. */ +body:has(.ff-home) .md-header { + background-color: transparent; + box-shadow: none; + transition: background-color 0.3s ease, box-shadow 0.3s ease; +} +body:has(.ff-home) .md-header--shadow { + background-color: rgba(11, 10, 20, 0.82); + backdrop-filter: blur(10px); + box-shadow: 0 1px 0 rgba(167, 139, 250, 0.14); +} + +.ff-home { + color: var(--ff-fg); + font-family: "Inter", system-ui, sans-serif; + font-size: 16px; + line-height: 1.6; + overflow: hidden; /* contain the hero glows */ +} +.ff-home *, +.ff-home *::before, +.ff-home *::after { box-sizing: border-box; } + +.ff-home a { text-decoration: none; } + +.ff-wrap { + max-width: 1120px; + margin-inline: auto; + padding-inline: 1.5rem; +} + +.ff-eyebrow { + font-family: var(--ff-display); + font-size: 0.74rem; + font-weight: 600; + letter-spacing: 0.22em; + text-transform: uppercase; + color: var(--ff-violet-bright); + margin: 0 0 1.1rem; +} + +.ff-grad { + background: var(--ff-wm); + -webkit-background-clip: text; + background-clip: text; + color: transparent; +} + +/* ---- Hero -------------------------------------------------------------- */ +.ff-hero { + position: relative; + padding-top: calc(var(--ff-header-h) + 5.5rem); + padding-bottom: 6rem; + text-align: center; + isolation: isolate; +} +.ff-constellation { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + z-index: -2; + display: block; +} +.ff-hero::before { /* layered violet ambient, echoing the banner */ + content: ""; + position: absolute; + inset: -20% -10% 0; + z-index: -1; + background: + radial-gradient(60% 55% at 22% 18%, rgba(124, 58, 237, 0.28), transparent 60%), + radial-gradient(60% 55% at 82% 10%, rgba(99, 102, 241, 0.22), transparent 60%), + radial-gradient(45% 40% at 50% 90%, rgba(76, 29, 149, 0.30), transparent 70%); + pointer-events: none; +} + +.ff-hero__title { + font-family: var(--ff-display); + font-weight: 700; + font-size: clamp(2.6rem, 6vw, 4.6rem); + line-height: 1.04; + letter-spacing: -0.025em; + margin: 0 auto 1.3rem; + max-width: 16ch; +} +.ff-hero__lead { + font-size: clamp(1.05rem, 1.6vw, 1.28rem); + color: var(--ff-muted); + max-width: 60ch; + margin: 0 auto 2.2rem; +} +.ff-hero__lead code { + font-family: "JetBrains Mono", monospace; + font-size: 0.92em; + color: var(--ff-violet-pale); + background: rgba(167, 139, 250, 0.12); + padding: 0.08em 0.4em; + border-radius: 0.3rem; +} + +/* Install command */ +.ff-install { + display: inline-flex; + align-items: center; + gap: 0.7rem; + max-width: min(100%, 720px); + font-family: "JetBrains Mono", monospace; + font-size: 0.84rem; + color: var(--ff-fg); + background: rgba(20, 15, 30, 0.72); + border: 1px solid var(--ff-card-bd); + border-radius: 0.6rem; + padding: 0.65rem 0.65rem 0.65rem 1rem; + margin-bottom: 2.2rem; + box-shadow: 0 8px 30px rgba(0, 0, 0, 0.35); + text-align: left; +} +.ff-install__prompt { color: var(--ff-amber); user-select: none; flex: 0 0 auto; } +.ff-install__cmd { + color: var(--ff-fg); + flex: 1 1 auto; + min-width: 0; + overflow-x: auto; + white-space: nowrap; + scrollbar-width: thin; +} +.ff-install__cmd::-webkit-scrollbar { height: 4px; } +.ff-install__copy { + display: inline-grid; + place-items: center; + width: 2rem; height: 2rem; + border: 0; + border-radius: 0.4rem; + background: rgba(167, 139, 250, 0.14); + color: var(--ff-violet-bright); + cursor: pointer; + transition: background 0.2s, color 0.2s; +} +.ff-install__copy:hover { background: rgba(167, 139, 250, 0.28); color: #fff; } +.ff-install__copy svg { width: 1rem; height: 1rem; } +.ff-install__copy.is-copied { background: rgba(111, 207, 114, 0.22); color: #6fcf72; } +.ff-install__copy.is-copied svg { display: none; } +.ff-install__copy.is-copied::after { content: "\2713"; font-size: 1rem; line-height: 1; } /* check mark */ + +/* CTAs */ +.ff-cta-row { + display: flex; + flex-wrap: wrap; + gap: 0.8rem; + justify-content: center; +} +.ff-btn { + display: inline-flex; + align-items: center; + gap: 0.5rem; + font-family: var(--ff-display); + font-weight: 600; + font-size: 0.95rem; + padding: 0.72rem 1.4rem; + border-radius: 0.6rem; + border: 1px solid transparent; + transition: transform 0.15s ease, box-shadow 0.2s ease, background 0.2s ease, border-color 0.2s ease; +} +.ff-btn svg { width: 1.05rem; height: 1.05rem; } +.ff-btn--primary { + color: #fff; + background: linear-gradient(180deg, #8b5cf6, #7c3aed); + box-shadow: 0 10px 28px rgba(124, 58, 237, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.2); +} +.ff-btn--primary:hover { transform: translateY(-2px); box-shadow: 0 16px 40px rgba(124, 58, 237, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.25); } +.ff-btn--ghost { + color: var(--ff-fg); + background: rgba(167, 139, 250, 0.06); + border-color: var(--ff-card-bd); +} +.ff-btn--ghost:hover { background: rgba(167, 139, 250, 0.16); border-color: var(--ff-card-bd-hot); transform: translateY(-2px); } + +/* ---- Trust bar --------------------------------------------------------- */ +.ff-trust { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 0.6rem 0.7rem; + padding-bottom: 3rem; +} +.ff-chip { + font-family: var(--ff-display); + font-size: 0.82rem; + font-weight: 500; + color: var(--ff-muted); + background: var(--ff-card); + border: 1px solid var(--ff-card-bd); + border-radius: 999px; + padding: 0.38rem 0.9rem; +} +.ff-chip b { color: var(--ff-violet-bright); font-weight: 700; } +.ff-chip--amber { color: #ffce7a; } +.ff-chip--amber b { color: var(--ff-amber); } + +/* ---- Section scaffold -------------------------------------------------- */ +.ff-section { padding-block: 4.5rem; position: relative; } +.ff-section--tint { + background: linear-gradient(180deg, transparent, rgba(124, 58, 237, 0.05) 40%, transparent); +} +.ff-section__head { max-width: 62ch; margin: 0 auto 2.6rem; text-align: center; } +.ff-section__kicker { + font-family: var(--ff-display); + font-size: 0.74rem; + font-weight: 600; + letter-spacing: 0.2em; + text-transform: uppercase; + color: var(--ff-amber); + display: block; + margin-bottom: 0.7rem; +} +.ff-section__title { + font-family: var(--ff-display); + font-weight: 700; + font-size: clamp(1.8rem, 3.4vw, 2.6rem); + letter-spacing: -0.02em; + line-height: 1.1; + margin: 0 0 0.8rem; +} +.ff-section__sub { color: var(--ff-muted); font-size: 1.05rem; margin: 0; } + +/* ---- "Why" split ------------------------------------------------------- */ +.ff-why { + display: grid; + grid-template-columns: 1.05fr 0.95fr; + gap: 2.5rem; + align-items: center; +} +.ff-why__title { + font-family: var(--ff-display); + font-weight: 700; + font-size: clamp(1.7rem, 3vw, 2.4rem); + letter-spacing: -0.02em; + line-height: 1.12; + margin: 0 0 1.1rem; +} +.ff-why p { color: var(--ff-muted); margin: 0 0 1.4rem; } +.ff-why__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.9rem; } +.ff-why__list li { position: relative; padding-left: 1.7rem; color: var(--ff-fg); } +.ff-why__list li::before { + content: ""; + position: absolute; + left: 0; top: 0.45em; + width: 0.55rem; height: 0.55rem; + border-radius: 50%; + background: var(--ff-amber-grad); + box-shadow: 0 0 10px 1px rgba(246, 168, 33, 0.6); +} +.ff-why__list b { color: var(--ff-violet-bright); font-weight: 600; } + +/* ---- Feature grid ------------------------------------------------------ */ +.ff-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 1rem; +} +.ff-feat { + position: relative; + display: block; + background: var(--ff-card); + border: 1px solid var(--ff-card-bd); + border-radius: 0.8rem; + padding: 1.4rem 1.4rem 1.5rem; + transition: transform 0.18s ease, border-color 0.2s ease, background 0.2s ease; +} +.ff-feat::after { /* firefly dot, the recurring mark */ + content: ""; + position: absolute; + top: 1.4rem; right: 1.4rem; + width: 0.5rem; height: 0.5rem; + border-radius: 50%; + background: var(--ff-amber-grad); + opacity: 0.5; + box-shadow: 0 0 8px 1px rgba(246, 168, 33, 0.5); + transition: opacity 0.2s ease, box-shadow 0.2s ease; +} +.ff-feat:hover { + transform: translateY(-3px); + border-color: var(--ff-card-bd-hot); + background: var(--ff-card-2); +} +.ff-feat:hover::after { opacity: 1; box-shadow: 0 0 14px 2px rgba(246, 168, 33, 0.8); } +.ff-feat__name { + font-family: var(--ff-display); + font-weight: 600; + font-size: 1.08rem; + color: var(--ff-fg); + margin: 0 0 0.4rem; +} +.ff-feat__desc { color: var(--ff-muted); font-size: 0.92rem; margin: 0; } + +/* ---- Diagram frame ----------------------------------------------------- */ +.ff-figure { + background: rgba(245, 242, 254, 0.96); + border: 1px solid var(--ff-card-bd); + border-radius: 1rem; + padding: 1.4rem; + box-shadow: 0 24px 70px rgba(0, 0, 0, 0.45); + overflow: hidden; +} +.ff-figure img { display: block; width: 100%; height: auto; } +.ff-figure--pair { display: grid; grid-template-columns: 1fr 1fr; gap: 1.4rem; background: none; border: 0; box-shadow: none; padding: 0; } +.ff-figure--pair > .ff-figure { margin: 0; } +.ff-figcap { text-align: center; color: var(--ff-faint); font-size: 0.86rem; margin-top: 1rem; } + +/* ---- Pattern chips ----------------------------------------------------- */ +.ff-patterns { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.6rem; margin-top: 2rem; } +.ff-pattern { + font-family: var(--ff-display); + font-weight: 500; + font-size: 0.9rem; + color: var(--ff-fg); + background: var(--ff-card-2); + border: 1px solid var(--ff-card-bd); + border-radius: 0.5rem; + padding: 0.5rem 0.95rem; +} +.ff-pattern span { color: var(--ff-amber); } + +/* ---- Code showcase (CSS-only tabs) ------------------------------------- */ +.ff-code-wrap { max-width: 900px; margin-inline: auto; } +.ff-tabs { position: relative; } +.ff-tabs > input { position: absolute; opacity: 0; pointer-events: none; } +.ff-tabs__labels { + display: flex; + flex-wrap: wrap; + gap: 0.4rem; + margin-bottom: 0.8rem; + justify-content: center; +} +.ff-tabs__labels label { + font-family: var(--ff-display); + font-weight: 600; + font-size: 0.86rem; + color: var(--ff-muted); + padding: 0.45rem 1rem; + border-radius: 0.5rem; + border: 1px solid transparent; + cursor: pointer; + transition: color 0.2s, background 0.2s, border-color 0.2s; +} +.ff-tabs__labels label:hover { color: var(--ff-fg); } +.ff-window { + background: #0e0b18; + border: 1px solid var(--ff-card-bd); + border-radius: 0.8rem; + box-shadow: 0 24px 70px rgba(0, 0, 0, 0.5); + overflow: hidden; +} +.ff-window__bar { + display: flex; + align-items: center; + gap: 0.45rem; + padding: 0.7rem 1rem; + border-bottom: 1px solid rgba(167, 139, 250, 0.12); +} +.ff-window__bar i { width: 0.62rem; height: 0.62rem; border-radius: 50%; display: inline-block; } +.ff-window__bar i:nth-child(1) { background: #f6705a; } +.ff-window__bar i:nth-child(2) { background: #f6a821; } +.ff-window__bar i:nth-child(3) { background: #6fcf72; } +.ff-window__file { margin-left: 0.6rem; font-family: "JetBrains Mono", monospace; font-size: 0.78rem; color: var(--ff-faint); } +.ff-panel { display: none; margin: 0; } +.ff-code { + margin: 0; + padding: 1.3rem 1.4rem; + font-family: "JetBrains Mono", monospace; + font-size: 0.86rem; + line-height: 1.7; + color: #d8d2ea; + overflow-x: auto; + tab-size: 4; +} +.ff-code .k { color: #c4a8ff; } /* keyword */ +.ff-code .d { color: #f6a821; } /* decorator */ +.ff-code .s { color: #ffce7a; } /* string */ +.ff-code .c { color: var(--ff-faint); font-style: italic; } /* comment */ +.ff-code .f { color: #8be9fd; } /* call / attribute */ +.ff-code .o { color: var(--ff-violet-bright); } /* operator-ish */ +/* show the panel whose radio is checked + light its label */ +#ff-c1:checked ~ .ff-window .ff-panel.p1, +#ff-c2:checked ~ .ff-window .ff-panel.p2, +#ff-c3:checked ~ .ff-window .ff-panel.p3, +#ff-c4:checked ~ .ff-window .ff-panel.p4 { display: block; } +#ff-c1:checked ~ .ff-tabs__labels label[for="ff-c1"], +#ff-c2:checked ~ .ff-tabs__labels label[for="ff-c2"], +#ff-c3:checked ~ .ff-tabs__labels label[for="ff-c3"], +#ff-c4:checked ~ .ff-tabs__labels label[for="ff-c4"] { + color: #fff; + background: rgba(124, 58, 237, 0.28); + border-color: var(--ff-card-bd-hot); +} +.ff-tabs > input:focus-visible ~ .ff-tabs__labels label { outline: 2px solid var(--ff-violet-bright); outline-offset: 2px; } + +/* ---- Learn cards ------------------------------------------------------- */ +.ff-learn { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; } +.ff-learn__card { + display: block; + background: var(--ff-card); + border: 1px solid var(--ff-card-bd); + border-radius: 0.9rem; + padding: 1.6rem; + transition: transform 0.18s ease, border-color 0.2s ease, background 0.2s ease; +} +.ff-learn__card:hover { transform: translateY(-3px); border-color: var(--ff-card-bd-hot); background: var(--ff-card-2); } +.ff-learn__eyebrow { font-family: var(--ff-display); font-size: 0.72rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ff-amber); } +.ff-learn__title { font-family: var(--ff-display); font-weight: 700; font-size: 1.25rem; color: var(--ff-fg); margin: 0.6rem 0 0.5rem; } +.ff-learn__desc { color: var(--ff-muted); font-size: 0.92rem; margin: 0 0 0.9rem; } +.ff-learn__more { font-family: var(--ff-display); font-weight: 600; font-size: 0.88rem; color: var(--ff-violet-bright); } +.ff-learn__card:hover .ff-learn__more { color: #fff; } + +/* ---- Footer ------------------------------------------------------------ */ +.ff-foot { + border-top: 1px solid rgba(167, 139, 250, 0.14); + padding-block: 3rem 2.4rem; + margin-top: 2rem; + background: linear-gradient(180deg, transparent, rgba(76, 29, 149, 0.12)); +} +.ff-foot__grid { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1fr; gap: 2rem; } +.ff-foot__brand { display: flex; align-items: center; gap: 0.6rem; font-family: var(--ff-display); font-weight: 700; font-size: 1.15rem; color: #fff; } +.ff-foot__brand img { width: 1.7rem; height: 1.7rem; } +.ff-foot__tag { color: var(--ff-faint); font-size: 0.9rem; margin: 0.9rem 0 0; max-width: 34ch; } +.ff-foot h4 { font-family: var(--ff-display); font-size: 0.78rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ff-violet-bright); margin: 0 0 0.9rem; } +.ff-foot ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.55rem; } +.ff-foot a { color: var(--ff-muted); font-size: 0.92rem; } +.ff-foot a:hover { color: #fff; } +.ff-foot__base { border-top: 1px solid rgba(167, 139, 250, 0.1); margin-top: 2.4rem; padding-top: 1.6rem; display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.6rem; color: var(--ff-faint); font-size: 0.84rem; } + +/* ---- Scroll reveal --------------------------------------------------- */ +/* Intentionally none: landing content is always visible regardless of JS. + The hero constellation is the page's single animation. (.ff-reveal stays + in the markup as a harmless hook.) */ + +/* ---- Responsive -------------------------------------------------------- */ +@media (max-width: 900px) { + .ff-grid { grid-template-columns: repeat(2, 1fr); } + .ff-learn { grid-template-columns: 1fr; } + .ff-why { grid-template-columns: 1fr; } + .ff-figure--pair { grid-template-columns: 1fr; } + .ff-foot__grid { grid-template-columns: 1fr 1fr; } +} +@media (max-width: 560px) { + .ff-grid { grid-template-columns: 1fr; } + .ff-foot__grid { grid-template-columns: 1fr; } + .ff-install { width: 100%; justify-content: space-between; font-size: 0.82rem; } + .ff-hero { padding-top: calc(var(--ff-header-h) + 3rem); } +} + +/* ---- Reduced motion ---------------------------------------------------- */ +@media (prefers-reduced-motion: reduce) { + .ff-home *, + .ff-reveal { transition: none !important; animation: none !important; } + .ff-reveal { opacity: 1; transform: none; } +} diff --git a/docs/tutorial.md b/docs/tutorial.md index 89006ad5..cc171107 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -20,7 +20,7 @@ Copyright 2026 Firefly Software Foundation. Licensed under the Apache License 2. **Part I — Foundation** 1. [Introduction](#chapter-1-introduction) — What, who, why, design principles, running example -2. [Installation & Project Setup](#chapter-2-installation--project-setup) — UV, extras, `FireflyAgenticConfig`, model providers +2. [Installation & Project Setup](#chapter-2-installation-project-setup) — UV, extras, `FireflyAgenticConfig`, model providers 3. [Your First Agent](#chapter-3-your-first-agent) — `FireflyAgent`, `@firefly_agent`, registry, context, lifecycle *(diagram)* 4. [Tools](#chapter-4-tools) — `@firefly_tool`, `ToolBuilder`, guards, composition, built-ins, `ToolKit`, attaching tools to agents *(diagram)* 5. [Prompts](#chapter-5-prompts) — Jinja2 templates, versioning, composition, validation, file loading @@ -30,7 +30,7 @@ Copyright 2026 Firefly Software Foundation. Licensed under the Apache License 2. 6. [Reasoning Patterns](#chapter-6-reasoning-patterns) — ReAct, CoT, Plan-and-Execute, Reflexion, Tree of Thoughts, Goal Decomposition, custom patterns *(diagram)* 7. [Content Processing](#chapter-7-content-processing) — Chunking, batch processing, compression, sliding window 8. [Memory](#chapter-8-memory) — Conversation memory, working memory, backends, `MemoryManager`, forking, integration points *(diagram)* -9. [Validation & Quality of Service](#chapter-9-validation--quality-of-service) — Rules, `OutputValidator`, QoS checks, `OutputReviewer` +9. [Validation & Quality of Service](#chapter-9-validation-quality-of-service) — Rules, `OutputValidator`, QoS checks, `OutputReviewer` **Part III — Orchestration & Operations** diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 00000000..19ed492d --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,160 @@ +# Firefly Agentic — documentation site (MkDocs + Material). +# Local preview: pip install -r docs/requirements.txt && mkdocs serve +# Build (CI): mkdocs build --strict +site_name: Firefly Agentic +site_url: https://fireflyframework.github.io/fireflyframework-agentic/ +site_description: >- + The production-grade agentic metaframework, built on Pydantic AI. Keep + Pydantic AI's Agent, Tool and RunContext — gain lifecycle hooks, delegation, + memory, reasoning patterns, validation loops, RAG and DAG pipelines. +site_author: Firefly Software Foundation +copyright: Copyright © 2026 Firefly Software Foundation — Apache-2.0 + +repo_name: fireflyframework/fireflyframework-agentic +repo_url: https://github.com/fireflyframework/fireflyframework-agentic +edit_uri: edit/main/docs/ + +# Custom landing template lives OUTSIDE docs/ (Material requirement). +theme: + name: material + custom_dir: overrides + logo: assets/logo.svg + favicon: assets/favicon.svg + icon: + repo: fontawesome/brands/github + font: + text: Inter + code: JetBrains Mono + palette: + # Light scheme + - media: "(prefers-color-scheme: light)" + scheme: default + primary: deep purple + accent: deep purple + toggle: + icon: material/weather-night + name: Switch to dark mode + # Dark scheme — the firefly-in-the-dark default + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: deep purple + accent: deep purple + toggle: + icon: material/weather-sunny + name: Switch to light mode + features: + - navigation.tabs + - navigation.sections + - navigation.top + - navigation.tracking + - navigation.instant + - navigation.instant.progress + - navigation.footer + - navigation.indexes + - toc.follow + - search.suggest + - search.highlight + - search.share + - content.code.copy + - content.code.annotate + - content.tabs.link + +extra_css: + - stylesheets/firefly.css + +extra_javascript: + - javascripts/constellation.js + +extra: + homepage: https://fireflyframework.org/ + generator: false + social: + - icon: fontawesome/brands/github + link: https://github.com/fireflyframework/fireflyframework-agentic + name: Firefly Agentic on GitHub + - icon: material/web + link: https://fireflyframework.org/ + name: The Firefly Framework + +markdown_extensions: + - admonition + - attr_list + - md_in_html + - tables + - footnotes + - toc: + permalink: true + permalink_title: Anchor link to this section + - pymdownx.details + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format + - pymdownx.tabbed: + alternate_style: true + - pymdownx.highlight: + anchor_linenums: true + line_spans: __span + pygments_lang_class: true + - pymdownx.inlinehilite + - pymdownx.snippets: + base_path: ["."] + check_paths: true + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + - pymdownx.keys + - pymdownx.mark + - pymdownx.smartsymbols + +plugins: + - search + +# Keep internal working artifacts and non-content files out of the build. +exclude_docs: | + superpowers/ + plans/ + README.md + requirements.txt + +nav: + - Home: index.md + - Getting Started: + - Installation: getting-started/installation.md + - Quick Start: getting-started/quickstart.md + - The Tutorial: tutorial.md + - Jupyter Notebooks: getting-started/jupyter.md + - Architecture: architecture.md + - Agent Layer: + - Agents: agents.md + - Template Agents: templates.md + - Tools: tools.md + - Prompts: prompts.md + - Content: content.md + - Memory: memory.md + - Embeddings & Vector Stores: + - Embeddings: embeddings.md + - Vector Stores: vectorstores.md + - Intelligence: + - Reasoning Patterns: reasoning.md + - Validation & QoS: validation.md + - Security: + - Security: security.md + - Secure Script Execution: execution.md + - Observability: + - Observability: observability.md + - Resilience: resilience.md + - Storage: storage.md + - Explainability: explainability.md + - Experimentation: + - Experiments: experiments.md + - Lab: lab.md + - Orchestration: + - Pipeline: pipeline.md + - Dynamic Workflows: workflows.md + - Use Cases: + - IDP Pipeline: use-case-idp.md + - Reference: + - Migration Guide: migration.md + - Changelog: changelog.md diff --git a/overrides/home.html b/overrides/home.html new file mode 100644 index 00000000..01b433b0 --- /dev/null +++ b/overrides/home.html @@ -0,0 +1,341 @@ +{% extends "main.html" %} + + + +{% block extrahead %} + + + + +{% endblock %} + +{% block htmltitle %}Firefly Agentic — production-grade agents on Pydantic AI{% endblock %} + +{% block tabs %} +
+ + +
+ +
+

Open source · Apache-2.0 · Built on Pydantic AI

+

Agents you can run in production.

+

+ Firefly Agentic is the production-grade metaframework built on Pydantic AI. + Keep its Agent, Tool and RunContext — gain + lifecycle hooks, delegation, memory, reasoning patterns, validation loops, RAG + and DAG pipelines. Protocol-driven, swappable, no lock-in. +

+ +
+ $ + curl -fsSL https://raw.githubusercontent.com/fireflyframework/fireflyframework-agentic/main/install.sh | bash + +
+ + +
+
+ + +
+
+ Built on Pydantic AI + 28 protocols + 6 reasoning patterns + 8 embedding providers + 6 vector stores + Python 3.13+ + type-checked + Apache-2.0 +
+
+ + +
+
+
+
+ Why a metaframework +

Keep the engine.
Gain the architecture.

+

+ Pydantic AI gives you type-safe, model-agnostic agents. A production system + needs more: orchestration, validation-and-retry, memory across turns, + traces and budgets, experiments. Firefly Agentic supplies every one of + those as a dedicated, swappable layer — so your business logic never + couples to infrastructure. +

+
    +
  • Your Agent, Tool and RunContext APIs stay exactly as they are.
  • +
  • Lifecycle hooks, registries, delegation, memory, reasoning, validation and pipelines wrap them — all optional, all composable.
  • +
  • Switch models, swap a memory backend or replace a component without touching agent code. No vendor lock-in.
  • +
+
+
+ Anatomy of an agent run: a FireflyAgent wrapping pydantic_ai.Agent inside a ten-stage middleware chain, with delegation, fallback, caching and memory. +
+
+
+
+ + +
+ +
+ + +
+
+
+ Architecture +

Five layers, strict top-down flow

+

Core → Agent → Intelligence → Experimentation → Orchestration. Higher layers depend on lower ones, never the reverse.

+
+
+ Firefly Agentic architecture: one front door over five layers — Orchestration, Experimentation, Intelligence, Agent, Core — on the Pydantic AI engine. +
+

Every extension point is a @runtime_checkable protocol — implement it and the framework discovers your component by duck typing.

+
+ The runtime-checkable protocols — AgentLike, ToolProtocol, GuardProtocol, ReasoningPattern, StepExecutor, DelegationStrategy, CompressionStrategy, MemoryStore, ValidationRule, Chunker, EmbeddingProtocol, VectorStoreProtocol — each with its swappable implementations. +
+
+
+ + +
+
+
+ Five minutes in +

Familiar Python, all the way down

+

Async-first, typed, and decorator-friendly. Here's the shape of it.

+
+
+
+ + + + +
+ + + + +
+
+
assistant.py
+
from fireflyframework_agentic.agents import FireflyAgent
+
+agent = FireflyAgent(name="assistant", model="openai:gpt-4o")
+result = await agent.run("Summarize this contract in 3 bullets.")
+print(result.output)
+
from fireflyframework_agentic.memory import MemoryManager
+
+memory = MemoryManager(max_conversation_tokens=32_000)
+agent = FireflyAgent(name="bot", model="openai:gpt-4o", memory=memory)
+
+cid = memory.new_conversation()
+await agent.run("My name is Alice.", conversation_id=cid)
+await agent.run("What's my name?", conversation_id=cid)  # -> Alice
+
from fireflyframework_agentic.reasoning import ReActPattern
+
+react = ReActPattern(max_steps=5)
+result = await react.execute(agent, "What's the weather in London?")
+print(result.output)  # structured ReasoningResult + trace
+
from fireflyframework_agentic.pipeline.builder import PipelineBuilder
+from fireflyframework_agentic.pipeline.steps import AgentStep, CallableStep
+
+pipeline = (
+    PipelineBuilder("idp")
+    .add_node("classify", AgentStep(classifier))
+    .add_node("extract", AgentStep(extractor))
+    .add_node("validate", CallableStep(check))
+    .chain("classify", "extract", "validate")
+    .build()
+)
+result = await pipeline.run(inputs="Process this document")
+
+
+
+
+
+ + +
+
+
+ Intelligence layer +

Six reasoning patterns, one loop

+

Every pattern shares a reason → act → observe → continue template, produces a structured trace, and swaps its output mode per model.

+
+
+ Six reasoning patterns — ReAct, Chain of Thought, Plan-and-Execute, Reflexion, Tree of Thoughts, Goal Decomposition — on one reason/act/observe loop. +
+
+ ReAct + Chain of Thought + Plan-and-Execute + Reflexion + Tree of Thoughts + Goal Decomposition +
+
+
+ + +
+
+
+ Orchestration layer +

Declarative DAGs & code-defined workflows

+

A typed pipeline graph for structure; a Python DSL for deterministic, resumable orchestration. Use either, or both.

+
+
+
+ A typed DAG pipeline: a seven-phase IDP flow with fan-out/fan-in, a human-in-the-loop pause, checkpointing and an audit log. +
Pipeline — declarative DAG
+
+
+ Dynamic Workflows: the @workflow DSL primitives over a WorkflowContext carrying runner, journal, budget and routing, with verification helpers. +
Workflows — code-defined DSL
+
+
+
+
+ + +
+
+
+ Retrieval-augmented generation +

Bring your own embeddings & vector store

+

Eight embedding providers and six vector-store backends behind one protocol — drop straight into a pipeline with EmbeddingStep and RetrievalStep.

+
+
+ Retrieval-augmented generation: eight embedding providers and six vector-store backends behind the EmbeddingProtocol and VectorStoreProtocol. +
+
+
+ + +
+ +
+ + + + +
+{% endblock %} + +{% block content %}{% endblock %} +{% block footer %}{% endblock %}