Skip to content

Commit 2928a81

Browse files
authored
fix: Fix mas howto guide for new manifest models (#109)
* fix: more bugfixes Signed-off-by: Jeff Napper <103025963+jnapper7@users.noreply.github.com> * fix: fix error messages Signed-off-by: Jeff Napper <103025963+jnapper7@users.noreply.github.com> * fix: updates for new WFSM Signed-off-by: Jeff Napper <103025963+jnapper7@users.noreply.github.com> --------- Signed-off-by: Jeff Napper <103025963+jnapper7@users.noreply.github.com>
1 parent 7f667b0 commit 2928a81

4 files changed

Lines changed: 204 additions & 104 deletions

File tree

docs/pages/how-to-guides/agents/thread.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Building Applications with ACP Threads
2-
=====================================
2+
======================================
33

44
ACP Node supports threads, where a thread contains the accumulated state of a sequence of runs.
55

@@ -24,7 +24,7 @@ Prerequisites
2424

2525

2626
Implementation Walkthrough
27-
-------------------
27+
----------------------------
2828

2929
Together we will, create a LangGraph agent, deploy it on a Workflow Server, and utilize its threading capabilities. You can find the agent's source code here: `Mail Composer Agent Source Code <https://github.com/agntcy/agentic-apps/blob/main/mailcomposer/mailcomposer/mailcomposer.py>`_.
3030
The agent we will work with is called **Mail Composer**, which specializes in composing emails for marketing campaigns.

docs/pages/how-to-guides/mas-creation-tutorial/mas-tutorial.md

Lines changed: 201 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ Install the dependencies:
6161

6262
```bash
6363
# Add all dependencies
64-
poetry add python-dotenv langgraph langchain-openai langchain agntcy-acp
64+
poetry add python-dotenv langgraph langchain-openai langchain "agntcy-acp[iomapper-langgraph]"
6565

6666
# Install the current project (marketing-campaign) and dependencies
6767
poetry install
@@ -432,6 +432,14 @@ def build_app_graph() -> CompiledStateGraph:
432432
return graph
433433
```
434434

435+
At this point, if you want to run your application to see if it compiles [(as at the end of Step 1 above)](#skeleton-code-example), you will
436+
need to set the `SENDGRID_API_KEY` in your environment. This depends on your operating system and
437+
shell, but an example for most shells in most Unix-like OSes:
438+
439+
```shell
440+
export SENDGRID_API_KEY="enter API key here"
441+
```
442+
435443
For a complete setup guide including Tyk gateway configuration and SendGrid API details, see the [SendGrid API Bridge example in the ACP SDK documentation](https://docs.agntcy.org/pages/syntactic_sdk/api_bridge_agent.html#an-example-with-sendgrid-api).
436444

437445

@@ -670,6 +678,15 @@ With these additions, our application now has a complete workflow that can:
670678
6. Provide meaningful output back to the user
671679

672680

681+
At this point, if you want to run your application to see if it compiles [(as at the end of Step 1 above)](#skeleton-code-example), you will
682+
need to set some variables for Azure in your environment. This depends on your operating system
683+
and shell, but an example for most shells in most Unix-like OSes:
684+
685+
```shell
686+
export AZURE_OPENAI_API_KEY="enter API key here"
687+
export AZURE_OPENAI_ENDPOINT="https://resource.azure.openai.com/openai/"
688+
```
689+
673690
## Step 7: Generate Application Manifest
674691

675692
In this step, we will **generate the Agent Manifest** for our Marketing Campaign application. The manifest generation enables our application to be used by other applications and to be deployed through an [Agent Workflow Server](https://github.com/agntcy/workflow-srv).
@@ -685,94 +702,163 @@ Let's create a new file called `generate_manifest.py` in the `src/marketing_camp
685702

686703
```python
687704
# src/marketing_campaign/generate_manifest.py
705+
from datetime import datetime, timezone
688706
from pathlib import Path
689-
from pydantic import AnyUrl
690-
from marketing_campaign.state import OverallState, ConfigModel
707+
691708
from agntcy_acp.manifest import (
692-
AgentManifest,
693-
AgentDeployment,
694-
DeploymentOptions,
695-
LangGraphConfig,
696-
EnvVar,
697-
AgentMetadata,
698709
AgentACPSpec,
710+
AgentDependency,
711+
AgentDeployment,
712+
AgentManifest,
699713
AgentRef,
700714
Capabilities,
715+
DeploymentManifest,
716+
DeploymentOptions,
717+
EnvVar,
718+
LangGraphConfig,
719+
Locator,
720+
Manifest,
721+
Skill,
701722
SourceCodeDeployment,
702-
AgentDependency
723+
OASF_EXTENSION_NAME_MANIFEST,
703724
)
725+
from pydantic import AnyUrl
726+
727+
from marketing_campaign.state import ConfigModel, OverallState
704728

705-
mailcomposer_dependency_manifest = "./manifests/mailcomposer.json"
706-
email_reviewer_dependency_manifest = "./manifests/email_reviewer.json"
729+
# Deps are relative to the main manifest file.
730+
mailcomposer_dependency_manifest = "mailcomposer.json"
731+
email_reviewer_dependency_manifest = "email_reviewer.json"
707732

708733
manifest = AgentManifest(
709-
metadata=AgentMetadata(
710-
ref=AgentRef(name="org.agntcy.marketing-campaign", version="0.0.1", url=None),
711-
description="Offer a chat interface to compose an email for a marketing campaign. Final output is the email that could be used for the campaign"),
712-
specs=AgentACPSpec(
713-
input=OverallState.model_json_schema(),
714-
output=OverallState.model_json_schema(),
715-
config=ConfigModel.model_json_schema(),
716-
capabilities=Capabilities(
717-
threads=False,
718-
callbacks=False,
719-
interrupts=False,
720-
streaming=None
734+
name="org.agntcy.marketing-campaign",
735+
authors=["AGNTCY Internet of Agents Collective"],
736+
annotations={"type": "langgraph"},
737+
version="0.3.1",
738+
locators=[
739+
Locator(
740+
url="https://github.com/agntcy/agentic-apps/tree/main/marketing-campaign",
741+
type="source-code",
721742
),
722-
custom_streaming_update=None,
723-
thread_state=None,
724-
interrupts=None
725-
),
726-
deployment=AgentDeployment(
727-
deployment_options=[
728-
DeploymentOptions(
729-
root = SourceCodeDeployment(
730-
type="source_code",
731-
name="source_code_local",
732-
url=AnyUrl("file://."),
733-
framework_config=LangGraphConfig(
734-
framework_type="langgraph",
735-
graph="marketing_campaign.app:graph"
736-
)
737-
)
738-
)
739-
],
740-
env_vars=[EnvVar(name="AZURE_OPENAI_API_KEY", desc="Azure key for the OpenAI service"),
741-
EnvVar(name="AZURE_OPENAI_ENDPOINT", desc="Azure endpoint for the OpenAI service"),
742-
EnvVar(name="SENDGRID_API_KEY", desc="Sendgrid API key")],
743-
dependencies=[
744-
AgentDependency(
745-
name="mailcomposer",
746-
ref=AgentRef(name="org.agntcy.mailcomposer", version="0.0.1", url=f"file://{mailcomposer_dependency_manifest}"),
747-
deployment_option = None,
748-
env_var_values = None
743+
],
744+
description="Offer a chat interface to compose an email for a marketing campaign. Final output is the email that could be used for the campaign",
745+
created_at=datetime.now(timezone.utc).isoformat(timespec="seconds"),
746+
schema_version="0.1.3",
747+
skills=[
748+
Skill(
749+
category_name="Natural Language Processing",
750+
category_uid=1,
751+
class_name="Dialogue Generation",
752+
class_uid=10204,
753+
),
754+
Skill(
755+
category_name="Natural Language Processing",
756+
category_uid=1,
757+
class_name="Text Completion",
758+
class_uid=10201,
759+
),
760+
Skill(
761+
category_name="Natural Language Processing",
762+
category_uid=1,
763+
class_name="Text Paraphrasing",
764+
class_uid=10203,
765+
),
766+
Skill(
767+
category_name="Natural Language Processing",
768+
category_uid=1,
769+
class_name="Knowledge Synthesis",
770+
class_uid=10303,
771+
),
772+
Skill(
773+
category_name="Natural Language Processing",
774+
category_uid=1,
775+
class_name="Text Style Transfer",
776+
class_uid=10206,
777+
),
778+
Skill(
779+
category_name="Natural Language Processing",
780+
category_uid=1,
781+
class_name="Tone and Style Adjustment",
782+
class_uid=10602,
783+
),
784+
],
785+
extensions=[
786+
Manifest(
787+
name=OASF_EXTENSION_NAME_MANIFEST,
788+
version="v0.2.2",
789+
data=DeploymentManifest(
790+
acp=AgentACPSpec(
791+
input=OverallState.model_json_schema(),
792+
output=OverallState.model_json_schema(),
793+
config=ConfigModel.model_json_schema(),
794+
capabilities=Capabilities(
795+
threads=False, callbacks=False, interrupts=False, streaming=None
796+
),
797+
custom_streaming_update=None,
798+
thread_state=None,
799+
interrupts=None,
800+
),
801+
deployment=AgentDeployment(
802+
deployment_options=[
803+
DeploymentOptions(
804+
root=SourceCodeDeployment(
805+
type="source_code",
806+
name="source_code_local",
807+
url=AnyUrl("file://../"),
808+
framework_config=LangGraphConfig(
809+
framework_type="langgraph",
810+
graph="marketing_campaign.app:graph",
811+
),
812+
)
813+
)
814+
],
815+
env_vars=[
816+
EnvVar(
817+
name="AZURE_OPENAI_API_KEY",
818+
desc="Azure key for the OpenAI service",
819+
),
820+
EnvVar(
821+
name="AZURE_OPENAI_ENDPOINT",
822+
desc="Azure endpoint for the OpenAI service",
823+
),
824+
EnvVar(name="SENDGRID_API_KEY", desc="Sendgrid API key"),
825+
],
826+
agent_deps=[
827+
AgentDependency(
828+
name="mailcomposer",
829+
ref=AgentRef(
830+
name="org.agntcy.mailcomposer",
831+
version="0.0.1",
832+
url=AnyUrl(f"file://{mailcomposer_dependency_manifest}"),
833+
),
834+
deployment_option=None,
835+
env_var_values=None,
836+
),
837+
AgentDependency(
838+
name="email_reviewer",
839+
ref=AgentRef(
840+
name="org.agntcy.email_reviewer",
841+
version="0.0.1",
842+
url=AnyUrl(f"file://{email_reviewer_dependency_manifest}"),
843+
),
844+
deployment_option=None,
845+
env_var_values=None,
846+
),
847+
],
848+
),
749849
),
750-
AgentDependency(
751-
name="email_reviewer",
752-
ref=AgentRef(name="org.agntcy.email_reviewer", version="0.0.1", url=f"file://{email_reviewer_dependency_manifest}"),
753-
deployment_option = None,
754-
env_var_values = None
755-
)
756-
]
757-
)
850+
),
851+
],
758852
)
759853

760-
with open(f"{Path(__file__).parent.parent.parent}/manifests/marketing-campaign.json", "w") as f:
854+
with open(
855+
f"{Path(__file__).parent.parent.parent}/manifests/marketing-campaign.json", "w"
856+
) as f:
761857
json_content = manifest.model_dump_json(
762-
exclude_unset=True,
763-
exclude_none=True,
764-
indent=2
765-
)
766-
# Replace URLs with filesystem paths because file:// schema not yet supported on dependencies
767-
json_content = json_content.replace(
768-
f"file://{mailcomposer_dependency_manifest}",
769-
mailcomposer_dependency_manifest
770-
)
771-
json_content = json_content.replace(
772-
f"file://{email_reviewer_dependency_manifest}",
773-
email_reviewer_dependency_manifest
858+
exclude_unset=True, exclude_none=True, indent=2
774859
)
775860
f.write(json_content)
861+
f.write("\n")
776862
```
777863

778864
### Understanding the Manifest Generator Structure
@@ -836,11 +922,14 @@ After generating the manifest, we can deploy and run our application using the W
836922

837923
### Installing the Workflow Server Manager
838924

839-
First, download the Workflow Server Manager CLI appropriate for your operating system from the [releases page](https://github.com/agntcy/workflow-srv-mgr/releases). Make sure to execute these commands from the root directory of your project:
925+
First, download the Workflow Server Manager CLI appropriate for your operating system from
926+
the [releases page](https://github.com/agntcy/workflow-srv-mgr/releases). Note that the
927+
latest version may be later (semantically) than the version in the example below. Make sure
928+
to execute these commands from the root directory of your project:
840929

841930
```bash
842931
# For macOS with Apple Silicon (run from project root)
843-
curl -L https://github.com/agntcy/workflow-srv-mgr/releases/download/v0.1.1/wfsm0.1.1_darwin_arm64.tar.gz -o wfsm.tar.gz
932+
curl -L https://github.com/agntcy/workflow-srv-mgr/releases/download/v0.3.2/wfsm0.3.2_darwin_arm64.tar.gz -o wfsm.tar.gz
844933
tar -xzf wfsm.tar.gz # Keep the extracted wfsm binary it in the project root
845934
chmod +x wfsm
846935
# For other platforms, download the appropriate binary from the releases page
@@ -854,21 +943,32 @@ Before starting the workflow server, create a configuration file that provides t
854943

855944
```yaml
856945
# marketing_campaign_config.yaml
857-
values:
858-
AZURE_OPENAI_API_KEY: your_secret
859-
AZURE_OPENAI_ENDPOINT: "the_url.com"
860-
API_HOST: 0.0.0.0
861-
SENDGRID_HOST: http://host.docker.internal:8080
862-
SENDGRID_API_KEY: SG.your-api-key
863-
dependencies:
864-
- name: mailcomposer
865-
values:
866-
AZURE_OPENAI_API_KEY: your_secret
867-
AZURE_OPENAI_ENDPOINT: "the_url.com"
868-
- name: email_reviewer
869-
values:
870-
AZURE_OPENAI_API_KEY: your_secret
871-
AZURE_OPENAI_ENDPOINT: "the_url.com"
946+
config:
947+
email_reviewer:
948+
port: 0
949+
apiKey: 799cccc7-49e4-420a-b0a8-e4de949ae673
950+
id: 45fb3f84-c0d7-41fb-bae3-363ca8f8092a
951+
envVars:
952+
AZURE_OPENAI_API_KEY: "[YOUR AZURE OPEN API KEY]"
953+
AZURE_OPENAI_ENDPOINT: "https://[YOUR ENDPOINT].openai.azure.com"
954+
AZURE_OPENAI_API_VERSION: "2024-08-01-preview"
955+
mailcomposer:
956+
port: 0
957+
apiKey: a9ee3d6a-6950-4252-b2f0-ad70ce57d603
958+
id: 76363e34-d684-4cab-b2b7-2721c772e42f
959+
envVars:
960+
AZURE_OPENAI_API_KEY: "[YOUR AZURE OPEN API KEY]"
961+
AZURE_OPENAI_ENDPOINT: "https://[YOUR ENDPOINT].openai.azure.com"
962+
org.agntcy.marketing-campaign:
963+
port: 65222
964+
apiKey: 12737451-d333-41c2-b3dd-12f15fa59b38
965+
id: d6306461-ea6c-432f-b6a6-c4feaa81c19b
966+
envVars:
967+
AZURE_OPENAI_API_KEY: "[YOUR AZURE OPEN API KEY]"
968+
AZURE_OPENAI_ENDPOINT: "https://[YOUR ENDPOINT].openai.azure.com"
969+
SENDGRID_HOST: "http://host.docker.internal:8080"
970+
SENDGRID_API_KEY: "[YOUR SENDGRID_API_KEY]"
971+
LOG_LEVEL: debug
872972
```
873973

874974
> **Note**: Replace placeholder values with your actual API keys and endpoints. The `SENDGRID_HOST` is set to `http://host.docker.internal:8080` to allow communication with a API Bridge service that will locally run in Docker.
@@ -882,17 +982,18 @@ Before testing the full application workflow, you need to set up the SendGrid AP
882982
Now, deploy the Marketing Campaign workflow server using the manifest we generated. Run this command from the root directory of your project:
883983

884984
```bash
885-
./wfsm deploy -m ./manifests/marketing-campaign.json -e ./marketing_campaign_config.yaml
985+
./wfsm deploy -m ./manifests/marketing-campaign.json -c ./marketing_campaign_config.yaml --dryRun=false
886986
```
887987

888988
If the deployment is successful, you'll see output similar to:
889989
```plaintext
890-
2025-03-28T12:31:04+01:00 INF ---------------------------------------------------------------------
891-
2025-03-28T12:31:04+01:00 INF ACP agent deployment name: org.agntcy.marketing-campaign
892-
2025-03-28T12:31:04+01:00 INF ACP agent running in container: org.agntcy.marketing-campaign, listening for ACP request on: http://127.0.0.1:62609
893-
2025-03-28T12:31:04+01:00 INF Agent ID: eae32ada-aaf8-408c-bf0c-7654455ce6e3
894-
2025-03-28T12:31:04+01:00 INF API Key: 08817517-7000-48e9-94d8-01d22cf7d20a
895-
2025-03-28T12:31:04+01:00 INF ---------------------------------------------------------------------
990+
2025-06-16T15:53:19+02:00 INF ---------------------------------------------------------------------
991+
2025-06-16T15:53:19+02:00 INF ACP agent deployment name: org.agntcy.marketing-campaign
992+
2025-06-16T15:53:19+02:00 INF ACP agent running in container: org.agntcy.marketing-campaign, listening for ACP requests on: http://127.0.0.1:65222
993+
2025-06-16T15:53:19+02:00 INF Agent ID: d6306461-ea6c-432f-b6a6-c4feaa81c19b
994+
2025-06-16T15:53:19+02:00 INF API Key: 12737451-d333-41c2-b3dd-12f15fa59b38
995+
2025-06-16T15:53:19+02:00 INF API Docs: http://127.0.0.1:65222/agents/d6306461-ea6c-432f-b6a6-c4feaa81c19b/docs
996+
2025-06-16T15:53:19+02:00 INF ---------------------------------------------------------------------
896997
```
897998

898999
Take note of the **Agent ID**, **API Key**, and **Host** information, as you'll need them to interact with the deployed application.
@@ -908,11 +1009,11 @@ To test our application, we'll use an ACP client that allows us to communicate w
9081009
curl https://raw.githubusercontent.com/agntcy/agentic-apps/refs/heads/main/marketing-campaign/src/marketing_campaign/main_acp_client.py -o src/marketing_campaign/main_acp_client.py
9091010
```
9101011

911-
2. Set the environment variables with the information from your deployment logs:
1012+
2. Set the environment variables with the information from your configuration:
9121013
```bash
913-
export MARKETING_CAMPAIGN_HOST="http://localhost:62609" # Use the host from your logs
914-
export MARKETING_CAMPAIGN_ID="eae32ada-aaf8-408c-bf0c-7654455ce6e3" # Use your actual Agent ID
915-
export MARKETING_CAMPAIGN_API_KEY='{"x-api-key": "08817517-7000-48e9-94d8-01d22cf7d20a"}' # Use your actual API Key
1014+
export MARKETING_CAMPAIGN_HOST="http://localhost:65222" # Use the host from your logs
1015+
export MARKETING_CAMPAIGN_ID="d6306461-ea6c-432f-b6a6-c4feaa81c19b" # Use your actual Agent ID
1016+
export MARKETING_CAMPAIGN_API_KEY='{"x-api-key": "12737451-d333-41c2-b3dd-12f15fa59b38"}' # Use your actual API Key
9161017

9171018
# Configuration of the application
9181019
export RECIPIENT_EMAIL_ADDRESS="recipient@example.com"

0 commit comments

Comments
 (0)