* Python: Split type checkers by target (pyright source, 5 checkers on tests/samples) Rework the typing setup along the lines of the 'too many type checkers' approach: - Pyright (strict) is now the sole source-code type checker; mypy is removed from source and its [tool.mypy] block becomes a relaxed profile used only for tests/samples. - Tests are checked by all five checkers (pyright relaxed, mypy, pyrefly, ty, zuban); samples by pyright, pyrefly, and ty. All run in a relaxed/ basic profile so authors aren't forced into over-annotation. - Add pyrightconfig.tests.json and bump sample pyright configs to basic. - Unify test/sample typing onto the same parallel fan-out used by source pyright via run_command_items in task_runner.py. - Make version-conditional imports symmetric: keep or drop the '# type: ignore' on both branches so results match across interpreter versions (local vs CI). - Update SKILL.md, DEV_SETUP.md, and CODING_STANDARD.md for the five gating checkers and pyright on source+tests+samples. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Fix merge regressions from main (typing + runtime) Merging main into the type-checker split branch surfaced regressions that the new five-checker test suite and unit tests caught: Runtime fixes: - anthropic: restore the dropped `cache_read_input_token_count` mapping in _parse_usage_from_anthropic (lost during merge conflict resolution). - gemini: _get_function_calling_mode test helper returned str(enum) ('FunctionCallingConfigMode.AUTO') instead of the enum value ('AUTO'). - openai: _response_id_from_token test helper was an infinite self-recursion; return token['response_id']. - orchestrations: reset output_events per approval iteration so the terminal output assertion counts only the final run. - core: drop a stale duplicate harness test whose message ('non-negative') contradicted the source ('positive'). - purview: import PolicyLocation/PolicyScope/ProtectionScopeActivities/ ExecutionMode used by the processor tests. Type-checker fixes (tests, relaxed profile): - core: pyright/mypy/pyrefly/ty/zuban green-ups across the harness, MCP, observability and types tests. - anthropic/openai: route provider-namespaced UsageDetails keys through a dict cast (extra_items TypedDict unsupported by mypy/ty). - purview: typed model constructors and cache-mock casts. - ag-ui: annotate WorkflowContext[Any, Any] so yield_output accepts test payloads, guard Optional forwarded_props, and ty-ignore intentional bad args. Source pyright (sole source checker) flagged unnecessary ignores newly introduced by merged code in core _tools.py and declarative _declarative_base.py. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Isolate per-package mypy cache in test-typing fan-out The parallel test-typing fan-out runs many mypy processes concurrently, all defaulting to a single shared ./.mypy_cache. Concurrent writes corrupt the cache and mypy aborts with INTERNAL ERROR (intermittently, depending on worker timing) -- which is why CI's Test Typing job failed on a shifting set of packages while a single-package run was fine. Give each mypy invocation an isolated cache dir keyed by its target paths so incremental caching still works per package without races. Other checkers (zuban/pyrefly/ty/pyright) maintain their own caches and are unaffected. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Make lab pyright-only on source (drop source mypy) Lab was the last package still running mypy on its source code, requiring mypy-only `# type: ignore` comments that pyright (the sole source checker everywhere else) flags as unnecessary. Align lab with the rest of the monorepo: - Remove the lab source mypy poe tasks (mypy-gaia/lightning/tau2) and the now-dead strict [tool.mypy] config block. - Drop the 'Run lab mypy' CI step; lab source is type-checked by pyright only. Lab tests remain covered by the workspace test-typing fan-out (mypy, pyrefly, ty, zuban, pyright over tests using the relaxed root config). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Fix test-typing regressions from latest main merge A fresh merge from main brought in new test code never run under the five-checker test-typing suite. Green up across the affected packages: - core: narrow Optional span.attributes with 'and' guards in span filters and assert+cast the json.loads(...attributes[...]) reads (test_observability); match the existing as_agent ignore on the protocol-typed fixture (test_clients). - openai: align new streaming tests with the established chat_options dict pattern (ChatOptions TypedDict isn't assignable to dict), route Optional .annotations[0] access through a small _first_annotation helper (mirrors the file's assert-not-None convention), and annotate a mapped ResponseStream. - foundry_hosting: annotate error: dict[str, Any] = body.get(...) or {} (zuban needs the annotation). - foundry: narrow ignores for the live AIProjectClient credential arg (pyrefly) and connections.get_default (zuban) SDK type gaps. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * updated pyright version * pyright fix * Python: Fix source typing for pyright 1.1.410 Pyright 1.1.410 tightened several checks. Apply the same source fixes as upstream PR #6275: - anthropic: import AsyncAnthropicBedrock from anthropic.lib.bedrock and AsyncAnthropicVertex from anthropic.lib.vertex (no longer re-exported from the anthropic top-level package -> reportPrivateImportUsage). - core _types.py: cast the transform-hook result to UpdateT (reportAssignmentType). - core _workflows/_events.py: annotate the @contextmanager helper as Generator[None] instead of Iterator[None] (reportDeprecated). - redis: build the combined filter expression with an explicit loop instead of reduce(and_, ...), which pyright could no longer fully type (drops the now unused functools.reduce / operator.and_ imports). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Accept plain-text body in Azure Functions workflow/run endpoint The workflow_orchestrator already accepts plain strings as well as JSON objects via context.get_input(), but the start_workflow_orchestration HTTP handler only accepted JSON and returned 400 for any non-JSON body. This made the functions integration tests that POST text/plain to /api/workflow/run (e.g. test_09_workflow_shared_state) fail consistently with 400 != 202. Fall back to the raw request body (decoded as UTF-8) when the body is not JSON, rejecting only a truly empty body. The JSON path is unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Redis Context Provider Examples
The Redis context provider enables persistent, searchable memory for your agents using Redis (RediSearch). It supports full‑text search and optional hybrid search with vector embeddings, letting agents remember and retrieve user context across sessions and threads.
This folder contains an example demonstrating how to use the Redis context provider with the Agent Framework.
Examples
| File | Description |
|---|---|
azure_redis_conversation.py |
Demonstrates conversation persistence with RedisHistoryProvider and Azure Redis with Azure AD (Entra ID) authentication using credential provider. |
redis_basics.py |
Shows standalone provider usage and agent integration. Demonstrates writing messages to Redis, retrieving context via full‑text or hybrid vector search, and persisting preferences across threads. Also includes a simple tool example whose outputs are remembered. |
redis_conversation.py |
Simple example showing conversation persistence with RedisContextProvider using traditional connection string authentication. |
redis_sessions.py |
Demonstrates memory scoping strategies. Includes: (1) global memory scope with application_id, agent_id, and user_id shared across operations; (2) hybrid vector search using a custom OpenAI vectorizer for richer context retrieval; and (3) multiple agents with isolated memory via different agent_id values. |
Prerequisites
Required resources
- A running Redis with RediSearch (Redis Stack or a managed service)
- Python environment with Agent Framework Redis extra installed
- Azure AI Foundry project endpoint and Azure OpenAI Responses deployment
- Optional: OpenAI API key if using vector embeddings
Install the package
pip install "agent-framework-redis"
Running Redis
Pick one option:
Option A: Docker (local Redis Stack)
docker run --name redis -p 6379:6379 -d redis:8.0.3
Option B: Redis Cloud
Create a free database and get the connection URL at https://redis.io/cloud/.
Option C: Azure Managed Redis
See quickstart: https://learn.microsoft.com/azure/redis/quickstart-create-managed-redis
Configuration
Environment variables
FOUNDRY_PROJECT_ENDPOINT(required): Azure AI Foundry project endpoint forFoundryChatClientFOUNDRY_MODEL(required): Foundry model deployment nameOPENAI_API_KEY(optional): Required only if you setvectorizer_choice="openai"to enable hybrid search.
Provider configuration highlights
The provider supports both full‑text only and hybrid vector search:
- Set
vectorizer_choiceto"openai"or"hf"to enable embeddings and hybrid search. - When using a vectorizer, also set
vector_field_name(e.g.,"vector"). - Partition fields for scoping memory:
application_id,agent_id,user_id. - Index management:
index_name,overwrite_redis_index,drop_redis_index.
What the example does
redis_basics.py walks through three scenarios:
- Standalone provider usage: adds messages and retrieves context via
invoking. - Agent integration: teaches the agent a preference and verifies it is remembered across turns.
- Agent + tool: calls a sample tool (flight search) and then asks the agent to recall details remembered from the tool output.
It uses FoundryChatClient for chat and, in some steps, optional OpenAI embeddings for hybrid search.
How to run
-
Start Redis (see options above). For local default, ensure it's reachable at
redis://localhost:6379. -
Set Azure Foundry/OpenAI responses environment variables:
export FOUNDRY_PROJECT_ENDPOINT="https://<resource>.services.ai.azure.com/api/projects/<project>"
export FOUNDRY_MODEL="<deployment-name>"
- (Optional) Set your OpenAI key if using embeddings:
export OPENAI_API_KEY="<your key>"
- Run the example:
python redis_basics.py
You should see the agent responses and, when using embeddings, context retrieved from Redis. The example includes commented debug helpers you can print, such as index info or all stored docs.
Key concepts
Memory scoping
- Global scope: set
application_id,agent_id, oruser_idon the provider to filter memory. - Agent isolation: use different
agent_idvalues to keep memories separated for different agent personas.
Hybrid vector search (optional)
- Enable by setting
vectorizer_choiceto"openai"(requiresOPENAI_API_KEY) or"hf"(offline model). - Provide
vector_field_name(e.g.,"vector"); other vector settings have sensible defaults.
Index lifecycle controls
overwrite_redis_indexanddrop_redis_indexhelp recreate indexes during iteration.
Troubleshooting
- Ensure at least one of
application_id,agent_id, oruser_idis set; the provider requires a scope. - Verify
FOUNDRY_PROJECT_ENDPOINTandFOUNDRY_MODELare set for the chat client. - If using embeddings, verify
OPENAI_API_KEYis set and reachable. - Make sure Redis exposes RediSearch (Redis Stack image or managed service with search enabled).